aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitattributes2
-rw-r--r--.gitignore12
-rw-r--r--INSTALL.md3
-rw-r--r--README.bootstrap10
-rw-r--r--bootstrap/bin/start.bootbin5328 -> 5330 bytes
-rw-r--r--bootstrap/bin/start.script8
-rw-r--r--bootstrap/bin/start_clean.bootbin5328 -> 5330 bytes
-rw-r--r--bootstrap/bin/start_clean.script8
-rw-r--r--bootstrap/lib/compiler/ebin/beam_asm.beambin9028 -> 9028 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_block.beambin12964 -> 13136 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_validator.beambin31328 -> 31328 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/compile.beambin31432 -> 31504 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/compiler.app2
-rw-r--r--bootstrap/lib/compiler/ebin/compiler.appup2
-rw-r--r--bootstrap/lib/compiler/ebin/core_lint.beambin10656 -> 10944 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/core_parse.beambin34380 -> 35236 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_codegen.beambin47904 -> 47932 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_core.beambin44984 -> 45376 bytes
-rw-r--r--bootstrap/lib/compiler/egen/core_parse.erl438
-rw-r--r--bootstrap/lib/kernel/ebin/dist_util.beambin9536 -> 9544 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/erl_epmd.beambin7612 -> 6576 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/gen_sctp.beambin3144 -> 3164 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/gen_tcp.beambin2184 -> 2284 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/gen_udp.beambin1436 -> 1536 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/hipe_unified_loader.beambin11428 -> 11428 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet6_sctp.beambin996 -> 1340 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_config.beambin8280 -> 8280 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_parse.beambin11968 -> 11968 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_sctp.beambin1728 -> 2068 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/kernel.app2
-rw-r--r--bootstrap/lib/kernel/ebin/net_kernel.beambin21112 -> 21108 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/beam_lib.beambin16584 -> 16584 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/c.beambin12520 -> 12520 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/digraph.beambin7712 -> 7728 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_internal.beambin4852 -> 4980 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_parse.beambin64988 -> 66176 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/file_sorter.beambin28196 -> 28196 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/ms_transform.beambin16892 -> 18684 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/otp_internal.beambin7816 -> 7952 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/qlc.beambin64200 -> 64200 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/stdlib.app2
-rw-r--r--bootstrap/lib/stdlib/ebin/supervisor.beambin14492 -> 14528 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/timer.beambin4840 -> 4876 bytes
-rw-r--r--bootstrap/lib/stdlib/egen/erl_parse.erl638
-rw-r--r--configure.in85
-rw-r--r--erts/aclocal.m481
-rwxr-xr-xerts/autoconf/configure.vxworks2
-rw-r--r--erts/autoconf/vxworks/sed.general4
-rwxr-xr-xerts/autoconf/win32.config.cache.static1
-rw-r--r--erts/configure.in177
-rw-r--r--erts/doc/src/driver.xml7
-rw-r--r--erts/doc/src/driver_entry.xml6
-rw-r--r--erts/doc/src/epmd.xml252
-rw-r--r--erts/doc/src/erl.xml49
-rw-r--r--erts/doc/src/erl_nif.xml44
-rw-r--r--erts/doc/src/erlang.xml275
-rw-r--r--erts/doc/src/notes.xml522
-rw-r--r--erts/emulator/Makefile.in39
-rw-r--r--erts/emulator/beam/atom.c2
-rw-r--r--erts/emulator/beam/atom.names2
-rw-r--r--erts/emulator/beam/beam_bif_load.c1
-rw-r--r--erts/emulator/beam/beam_debug.c2
-rw-r--r--erts/emulator/beam/beam_emu.c8
-rw-r--r--erts/emulator/beam/beam_load.c9
-rw-r--r--erts/emulator/beam/bif.h3
-rw-r--r--erts/emulator/beam/big.c88
-rw-r--r--erts/emulator/beam/big.h4
-rw-r--r--erts/emulator/beam/binary.c4
-rw-r--r--erts/emulator/beam/copy.c12
-rw-r--r--erts/emulator/beam/decl.h55
-rw-r--r--erts/emulator/beam/dist.c95
-rw-r--r--erts/emulator/beam/dist.h7
-rw-r--r--erts/emulator/beam/elib_malloc.c2334
-rw-r--r--erts/emulator/beam/elib_stat.h45
-rw-r--r--erts/emulator/beam/erl_alloc.c36
-rw-r--r--erts/emulator/beam/erl_async.c2
-rw-r--r--erts/emulator/beam/erl_bif_binary.c27
-rw-r--r--erts/emulator/beam/erl_bif_ddll.c5
-rw-r--r--erts/emulator/beam/erl_bif_info.c147
-rw-r--r--erts/emulator/beam/erl_bits.c4
-rw-r--r--erts/emulator/beam/erl_db.c10
-rw-r--r--erts/emulator/beam/erl_db_hash.c16
-rw-r--r--erts/emulator/beam/erl_db_tree.c14
-rw-r--r--erts/emulator/beam/erl_db_util.c21
-rw-r--r--erts/emulator/beam/erl_db_util.h2
-rw-r--r--erts/emulator/beam/erl_drv_thread.c2
-rw-r--r--erts/emulator/beam/erl_fun.c2
-rw-r--r--erts/emulator/beam/erl_gc.c50
-rw-r--r--erts/emulator/beam/erl_init.c41
-rw-r--r--erts/emulator/beam/erl_lock_check.c1
-rw-r--r--erts/emulator/beam/erl_message.c4
-rw-r--r--erts/emulator/beam/erl_message.h6
-rw-r--r--erts/emulator/beam/erl_nif.c36
-rw-r--r--erts/emulator/beam/erl_nif.h13
-rw-r--r--erts/emulator/beam/erl_nif_api_funcs.h21
-rw-r--r--erts/emulator/beam/erl_node_tables.c14
-rw-r--r--erts/emulator/beam/erl_node_tables.h2
-rw-r--r--erts/emulator/beam/erl_obsolete.c186
-rw-r--r--erts/emulator/beam/erl_process.c104
-rw-r--r--erts/emulator/beam/erl_process.h11
-rw-r--r--erts/emulator/beam/erl_time_sup.c20
-rw-r--r--erts/emulator/beam/export.c2
-rw-r--r--erts/emulator/beam/global.h6
-rw-r--r--erts/emulator/beam/io.c26
-rw-r--r--erts/emulator/beam/register.c2
-rw-r--r--erts/emulator/beam/sys.h50
-rw-r--r--erts/emulator/beam/time.c62
-rw-r--r--erts/emulator/beam/utils.c4
-rw-r--r--erts/emulator/drivers/common/efile_drv.c2
-rw-r--r--erts/emulator/drivers/common/inet_drv.c855
-rw-r--r--erts/emulator/drivers/unix/mem_drv.c145
-rw-r--r--erts/emulator/drivers/unix/unix_efile.c6
-rw-r--r--erts/emulator/drivers/win32/mem_drv.c141
-rw-r--r--erts/emulator/hipe/hipe_amd64_glue.S4
-rw-r--r--erts/emulator/hipe/hipe_arm_glue.S2
-rw-r--r--erts/emulator/hipe/hipe_bif0.c5
-rw-r--r--erts/emulator/hipe/hipe_bif1.c49
-rw-r--r--erts/emulator/hipe/hipe_ppc_glue.S4
-rw-r--r--erts/emulator/hipe/hipe_sparc_glue.S2
-rw-r--r--erts/emulator/hipe/hipe_x86_glue.S6
-rw-r--r--erts/emulator/hipe/hipe_x86_signal.c9
-rw-r--r--erts/emulator/obsolete/driver.h263
-rw-r--r--erts/emulator/sys/common/erl_mseg.c8
-rw-r--r--erts/emulator/sys/common/erl_poll.c39
-rw-r--r--erts/emulator/sys/unix/sys.c7
-rw-r--r--erts/emulator/sys/unix/sys_float.c40
-rw-r--r--erts/emulator/sys/win32/sys.c16
-rw-r--r--erts/emulator/test/Makefile1
-rw-r--r--erts/emulator/test/distribution_SUITE.erl93
-rw-r--r--erts/emulator/test/float_SUITE.erl29
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_SUITE.c68
-rw-r--r--erts/emulator/test/obsolete_SUITE.erl123
-rw-r--r--erts/emulator/test/obsolete_SUITE_data/Makefile.src33
-rw-r--r--erts/emulator/test/obsolete_SUITE_data/erl_threads.c302
-rw-r--r--erts/emulator/test/obsolete_SUITE_data/testcase_driver.c262
-rw-r--r--erts/emulator/test/obsolete_SUITE_data/testcase_driver.h57
-rw-r--r--erts/emulator/test/port_SUITE.erl10
-rw-r--r--erts/emulator/test/port_SUITE_data/Makefile.src2
-rw-r--r--erts/emulator/test/port_SUITE_data/dead_port.c102
-rw-r--r--erts/emulator/test/scheduler_SUITE.erl133
-rw-r--r--erts/emulator/test/send_term_SUITE.erl4
-rw-r--r--erts/emulator/test/system_info_SUITE.erl1
-rw-r--r--erts/emulator/test/time_SUITE.erl37
-rw-r--r--erts/epmd/src/Makefile.in29
-rw-r--r--erts/epmd/src/epmd.c55
-rw-r--r--erts/epmd/src/epmd.h21
-rw-r--r--erts/epmd/src/epmd_cli.c8
-rw-r--r--erts/epmd/src/epmd_int.h9
-rw-r--r--erts/epmd/src/epmd_srv.c218
-rw-r--r--erts/epmd/test/epmd_SUITE.erl356
-rw-r--r--erts/etc/common/Makefile.in10
-rw-r--r--erts/etc/common/dialyzer.c10
-rw-r--r--erts/etc/common/erlc.c17
-rw-r--r--erts/etc/common/erlexec.c65
-rw-r--r--erts/etc/common/escript.c52
-rw-r--r--erts/etc/common/heart.c9
-rw-r--r--erts/etc/common/inet_gethost.c1
-rw-r--r--erts/etc/common/run_test.c19
-rw-r--r--erts/etc/common/typer.c7
-rw-r--r--erts/etc/unix/cerl.src10
-rw-r--r--erts/etc/unix/run_erl.c33
-rwxr-xr-xerts/etc/win32/cygwin_tools/vc/ld.sh8
-rw-r--r--erts/include/internal/erl_misc_utils.h5
-rw-r--r--erts/include/internal/ethr_mutex.h8
-rw-r--r--erts/include/internal/ethread.h2
-rw-r--r--erts/include/internal/gcc/ethr_atomic.h9
-rw-r--r--erts/lib_src/common/erl_misc_utils.c855
-rw-r--r--erts/lib_src/common/ethr_mutex.c88
-rw-r--r--erts/preloaded/ebin/erl_prim_loader.beambin50392 -> 50384 bytes
-rw-r--r--erts/preloaded/ebin/erlang.beambin24324 -> 24316 bytes
-rw-r--r--erts/preloaded/ebin/init.beambin44352 -> 44856 bytes
-rw-r--r--erts/preloaded/ebin/otp_ring0.beambin1436 -> 1428 bytes
-rw-r--r--erts/preloaded/ebin/prim_file.beambin30544 -> 30536 bytes
-rw-r--r--erts/preloaded/ebin/prim_inet.beambin57272 -> 65184 bytes
-rw-r--r--erts/preloaded/ebin/prim_zip.beambin22440 -> 22428 bytes
-rw-r--r--erts/preloaded/ebin/zlib.beambin10620 -> 10612 bytes
-rw-r--r--erts/preloaded/src/Makefile22
-rw-r--r--erts/preloaded/src/init.erl64
-rw-r--r--erts/preloaded/src/prim_inet.erl254
-rw-r--r--erts/test/Makefile9
-rw-r--r--erts/test/autoimport_SUITE.erl163
-rw-r--r--erts/test/autoimport_SUITE_data/dummy.txt19
-rw-r--r--erts/test/erlc_SUITE.erl16
-rw-r--r--erts/test/erlexec_SUITE.erl24
-rw-r--r--erts/vsn.mk4
-rw-r--r--lib/.gitignore1
-rw-r--r--lib/appmon/doc/src/notes.xml16
-rw-r--r--lib/appmon/src/appmon_web.erl8
-rw-r--r--lib/appmon/vsn.mk20
-rw-r--r--lib/asn1/c_src/asn1_erl_driver.c3
-rw-r--r--lib/asn1/doc/src/asn1_ug.xml113
-rw-r--r--lib/asn1/doc/src/notes.xml44
-rw-r--r--lib/asn1/src/asn1.appup.src108
-rw-r--r--lib/asn1/src/asn1_records.hrl13
-rw-r--r--lib/asn1/src/asn1ct.erl2
-rw-r--r--lib/asn1/src/asn1ct_check.erl280
-rw-r--r--lib/asn1/src/asn1ct_constructed_ber.erl41
-rw-r--r--lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl31
-rw-r--r--lib/asn1/src/asn1ct_constructed_per.erl369
-rw-r--r--lib/asn1/src/asn1ct_gen.erl22
-rw-r--r--lib/asn1/src/asn1ct_gen_ber.erl13
-rw-r--r--lib/asn1/src/asn1ct_gen_ber_bin_v2.erl14
-rw-r--r--lib/asn1/src/asn1ct_gen_per.erl23
-rw-r--r--lib/asn1/src/asn1ct_gen_per_rt2ct.erl23
-rw-r--r--lib/asn1/src/asn1ct_parser2.erl527
-rw-r--r--lib/asn1/src/asn1ct_tok.erl184
-rw-r--r--lib/asn1/src/asn1rt_uper_bin.erl29
-rw-r--r--lib/asn1/test/Makefile29
-rw-r--r--lib/asn1/test/asn1_SUITE.erl.src23
-rw-r--r--lib/asn1/test/asn1_SUITE_data/AA2.asn1dbbin5224 -> 5910 bytes
-rw-r--r--lib/asn1/test/asn1_SUITE_data/EUTRA-RRC-Definitions.asn5795
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn82
-rw-r--r--lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl132
-rw-r--r--lib/asn1/test/asn1_appup_test.erl2
-rw-r--r--lib/asn1/test/test_compile_options.erl2
-rw-r--r--lib/asn1/vsn.mk323
-rw-r--r--lib/common_test/AUTHORS1
-rw-r--r--lib/common_test/doc/src/config_file_chapter.xml39
-rw-r--r--lib/common_test/doc/src/notes.xml63
-rw-r--r--lib/common_test/priv/Makefile.in4
-rw-r--r--lib/common_test/src/ct.erl2
-rw-r--r--lib/common_test/src/ct_config.erl38
-rw-r--r--lib/common_test/src/ct_logs.erl19
-rw-r--r--lib/common_test/src/ct_run.erl45
-rw-r--r--lib/common_test/src/ct_slave.erl58
-rw-r--r--lib/common_test/src/ct_util.erl31
-rw-r--r--lib/common_test/test/Makefile4
-rw-r--r--lib/common_test/test/ct_config_SUITE.erl29
-rw-r--r--lib/common_test/test/ct_master_SUITE.erl2
-rw-r--r--lib/common_test/test/ct_misc_1_SUITE.erl62
-rw-r--r--lib/common_test/test/ct_repeat_1_SUITE.erl1537
-rw-r--r--lib/common_test/test/ct_repeat_1_SUITE_data/repeat_1_SUITE.erl373
-rw-r--r--lib/common_test/test/ct_sequence_1_SUITE.erl300
-rw-r--r--lib/common_test/test/ct_sequence_1_SUITE_data/subgroups_1_SUITE.erl108
-rw-r--r--lib/compiler/doc/src/notes.xml15
-rw-r--r--lib/compiler/src/beam_block.erl35
-rw-r--r--lib/compiler/src/beam_validator.erl2
-rw-r--r--lib/compiler/src/cerl.erl6
-rw-r--r--lib/compiler/src/compile.erl4
-rw-r--r--lib/compiler/src/core_lint.erl25
-rw-r--r--lib/compiler/src/v3_codegen.erl4
-rw-r--r--lib/compiler/src/v3_core.erl78
-rw-r--r--lib/compiler/test/bs_bincomp_SUITE.erl38
-rw-r--r--lib/compiler/test/bs_construct_SUITE.erl4
-rw-r--r--lib/compiler/test/receive_SUITE.erl25
-rw-r--r--lib/compiler/vsn.mk2
-rw-r--r--lib/cosEvent/vsn.mk14
-rw-r--r--lib/cosEventDomain/vsn.mk14
-rw-r--r--lib/cosFileTransfer/test/Makefile132
-rw-r--r--lib/cosFileTransfer/test/cosFileTransfer.spec1
-rw-r--r--lib/cosFileTransfer/test/fileTransfer_SUITE.erl954
-rw-r--r--lib/cosFileTransfer/vsn.mk15
-rw-r--r--lib/cosNotification/doc/src/notes.xml70
-rw-r--r--lib/cosNotification/src/cosNotification_Filter.erl32
-rw-r--r--lib/cosNotification/vsn.mk19
-rw-r--r--lib/cosProperty/vsn.mk12
-rw-r--r--lib/cosTime/vsn.mk12
-rw-r--r--lib/cosTransactions/vsn.mk13
-rw-r--r--lib/crypto/c_src/Makefile.in24
-rw-r--r--lib/crypto/c_src/crypto.c29
-rw-r--r--lib/crypto/doc/src/notes.xml50
-rw-r--r--lib/crypto/src/crypto.erl35
-rw-r--r--lib/crypto/test/crypto_SUITE.erl19
-rw-r--r--lib/crypto/vsn.mk2
-rw-r--r--lib/debugger/doc/src/notes.xml16
-rw-r--r--lib/debugger/src/dbg_debugged.erl4
-rw-r--r--lib/debugger/test/Makefile106
-rw-r--r--lib/debugger/test/andor_SUITE.erl305
-rw-r--r--lib/debugger/test/bs_bincomp_SUITE.erl106
-rw-r--r--lib/debugger/test/bs_construct_SUITE.erl432
-rw-r--r--lib/debugger/test/bs_match_bin_SUITE.erl114
-rw-r--r--lib/debugger/test/bs_match_int_SUITE.erl230
-rw-r--r--lib/debugger/test/bs_match_misc_SUITE.erl152
-rw-r--r--lib/debugger/test/bs_match_tail_SUITE.erl106
-rw-r--r--lib/debugger/test/bs_utf_SUITE.erl292
-rw-r--r--lib/debugger/test/bug_SUITE.erl79
-rw-r--r--lib/debugger/test/bug_SUITE_data/Makefile.src25
-rw-r--r--lib/debugger/test/bug_SUITE_data/otp2163.erl60
-rw-r--r--lib/debugger/test/bug_SUITE_data/otp4845.erl52
-rw-r--r--lib/debugger/test/cleanup.erl45
-rw-r--r--lib/debugger/test/dbg_ui_SUITE.erl288
-rw-r--r--lib/debugger/test/dbg_ui_SUITE_data/manual_data/src/lists1.erl469
-rw-r--r--lib/debugger/test/dbg_ui_SUITE_data/manual_data/src/ordsets1.erl188
-rw-r--r--lib/debugger/test/dbg_ui_SUITE_data/manual_data/src/test.erl157
-rw-r--r--lib/debugger/test/debugger.spec1
-rw-r--r--lib/debugger/test/debugger_SUITE.erl123
-rw-r--r--lib/debugger/test/debugger_test.erl154
-rw-r--r--lib/debugger/test/debugger_testdoc.fm5bin0 -> 28672 bytes
-rw-r--r--lib/debugger/test/erl_eval_SUITE.erl1388
-rw-r--r--lib/debugger/test/exception_SUITE.erl256
-rw-r--r--lib/debugger/test/fun_SUITE.erl233
-rw-r--r--lib/debugger/test/guard_SUITE.erl1479
-rw-r--r--lib/debugger/test/int_SUITE.erl277
-rw-r--r--lib/debugger/test/int_SUITE_data/Makefile.src39
-rw-r--r--lib/debugger/test/int_SUITE_data/guards.erl108
-rw-r--r--lib/debugger/test/int_SUITE_data/lists1.erl469
-rw-r--r--lib/debugger/test/int_SUITE_data/my_lists.erl5681
-rw-r--r--lib/debugger/test/int_SUITE_data/ordsets1.erl191
-rw-r--r--lib/debugger/test/int_SUITE_data/test.erl152
-rw-r--r--lib/debugger/test/int_SUITE_data/test1.erl34
-rw-r--r--lib/debugger/test/int_break_SUITE.erl92
-rw-r--r--lib/debugger/test/int_break_SUITE_data/Makefile.src25
-rw-r--r--lib/debugger/test/int_break_SUITE_data/ordsets1.erl188
-rw-r--r--lib/debugger/test/int_eval_SUITE.erl277
-rw-r--r--lib/debugger/test/int_eval_SUITE_data/Makefile.src26
-rw-r--r--lib/debugger/test/int_eval_SUITE_data/my_int_eval_module.erl245
-rw-r--r--lib/debugger/test/lc_SUITE.erl74
-rw-r--r--lib/debugger/test/record_SUITE.erl252
-rw-r--r--lib/debugger/test/test_lib.erl29
-rw-r--r--lib/debugger/test/trycatch_SUITE.erl796
-rw-r--r--lib/debugger/vsn.mk2
-rw-r--r--lib/dialyzer/RELEASE_NOTES15
-rw-r--r--lib/dialyzer/doc/src/dialyzer.xml14
-rwxr-xr-xlib/dialyzer/doc/src/notes.xml15
-rw-r--r--lib/dialyzer/src/dialyzer_cl.erl4
-rw-r--r--lib/dialyzer/src/dialyzer_cl_parse.erl2
-rw-r--r--lib/dialyzer/src/dialyzer_plt.erl10
-rw-r--r--lib/dialyzer/src/dialyzer_races.erl38
-rw-r--r--lib/dialyzer/src/dialyzer_utils.erl12
-rw-r--r--lib/dialyzer/vsn.mk2
-rw-r--r--lib/docbuilder/doc/src/notes.xml16
-rw-r--r--lib/docbuilder/src/docb_edoc_xml_cb.erl27
-rw-r--r--lib/docbuilder/vsn.mk15
-rw-r--r--lib/edoc/doc/src/notes.xml15
-rw-r--r--lib/edoc/src/edoc.erl2
-rw-r--r--lib/edoc/src/edoc_report.erl2
-rw-r--r--lib/edoc/src/edoc_run.erl2
-rw-r--r--lib/edoc/vsn.mk2
-rw-r--r--lib/erl_docgen/doc/src/notes.xml17
-rw-r--r--lib/erl_docgen/priv/xsl/db_html.xsl4
-rw-r--r--lib/erl_docgen/vsn.mk23
-rw-r--r--lib/erl_interface/configure.in8
-rw-r--r--lib/erl_interface/doc/src/ei_connect.xml33
-rw-r--r--lib/erl_interface/doc/src/erl_connect.xml29
-rw-r--r--lib/erl_interface/doc/src/notes.xml68
-rw-r--r--lib/erl_interface/src/connect/ei_connect.c22
-rw-r--r--lib/erl_interface/src/connect/ei_resolve.c4
-rw-r--r--lib/erl_interface/src/connect/eirecv.c16
-rw-r--r--lib/erl_interface/src/connect/send.c3
-rw-r--r--lib/erl_interface/src/connect/send_exit.c3
-rw-r--r--lib/erl_interface/src/connect/send_reg.c3
-rw-r--r--lib/erl_interface/src/epmd/ei_epmd.h11
-rw-r--r--lib/erl_interface/src/epmd/epmd_port.c77
-rw-r--r--lib/erl_interface/src/epmd/epmd_publish.c68
-rw-r--r--lib/erl_interface/src/misc/ei_format.c4
-rw-r--r--lib/erl_interface/src/misc/ei_portio.c2
-rw-r--r--lib/erl_interface/src/prog/erl_call.c165
-rw-r--r--lib/erl_interface/src/registry/reg_dump.c4
-rw-r--r--lib/erl_interface/src/registry/reg_restore.c2
-rw-r--r--lib/erl_interface/test/ei_accept_SUITE.erl46
-rw-r--r--lib/erl_interface/test/ei_connect_SUITE.erl7
-rw-r--r--lib/erl_interface/test/ei_format_SUITE.erl2
-rw-r--r--lib/erl_interface/test/ei_format_SUITE_data/ei_format_test.c2
-rw-r--r--lib/erl_interface/vsn.mk2
-rw-r--r--lib/et/doc/src/et.xml1
-rw-r--r--lib/et/doc/src/et_collector.xml1
-rw-r--r--lib/et/doc/src/et_selector.xml1
-rw-r--r--lib/et/doc/src/et_tutorial.xmlsrc1
-rw-r--r--lib/et/doc/src/et_viewer.xml1
-rw-r--r--lib/et/doc/src/notes.xml26
-rw-r--r--lib/et/src/et_wx_viewer.erl13
-rw-r--r--lib/et/test/Makefile3
-rw-r--r--lib/et/vsn.mk25
-rw-r--r--lib/gs/doc/src/gs.xml14
-rw-r--r--lib/gs/doc/src/gs_chapter1.xml14
-rw-r--r--lib/gs/doc/src/notes.xml22
-rw-r--r--lib/gs/vsn.mk2
-rw-r--r--lib/hipe/cerl/erl_bif_types.erl35
-rw-r--r--lib/hipe/cerl/erl_types.erl388
-rw-r--r--lib/hipe/doc/src/notes.xml23
-rw-r--r--lib/hipe/icode/hipe_beam_to_icode.erl4
-rw-r--r--lib/hipe/icode/hipe_icode_exceptions.erl10
-rw-r--r--lib/hipe/icode/hipe_icode_type.erl20
-rw-r--r--lib/hipe/main/hipe.erl4
-rw-r--r--lib/hipe/regalloc/hipe_graph_coloring_regalloc.erl52
-rw-r--r--lib/hipe/vsn.mk2
-rw-r--r--lib/hipe/x86/hipe_x86_spill_restore.erl40
-rw-r--r--lib/ic/test/Makefile277
-rw-r--r--lib/ic/test/c_client_erl_server_SUITE.erl315
-rw-r--r--lib/ic/test/c_client_erl_server_SUITE_data/Makefile.src145
-rw-r--r--lib/ic/test/c_client_erl_server_SUITE_data/c_client.c1760
-rw-r--r--lib/ic/test/c_client_erl_server_SUITE_data/c_erl_test.idl174
-rw-r--r--lib/ic/test/c_client_erl_server_SUITE_data/erl_server.erl28
-rw-r--r--lib/ic/test/c_client_erl_server_SUITE_data/m_i_impl.erl161
-rw-r--r--lib/ic/test/c_client_erl_server_proto_SUITE.erl315
-rw-r--r--lib/ic/test/c_client_erl_server_proto_SUITE_data/Makefile.src146
-rw-r--r--lib/ic/test/c_client_erl_server_proto_SUITE_data/c_client.c1763
-rw-r--r--lib/ic/test/c_client_erl_server_proto_SUITE_data/c_erl_test.idl173
-rw-r--r--lib/ic/test/c_client_erl_server_proto_SUITE_data/erl_server.erl28
-rw-r--r--lib/ic/test/c_client_erl_server_proto_SUITE_data/m_i_impl.erl161
-rw-r--r--lib/ic/test/c_client_erl_server_proto_SUITE_data/my.c50
-rw-r--r--lib/ic/test/c_client_erl_server_proto_tmo_SUITE.erl315
-rw-r--r--lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/Makefile.src146
-rw-r--r--lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/c_client.c1763
-rw-r--r--lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/c_erl_test.idl173
-rw-r--r--lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/erl_server.erl28
-rw-r--r--lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/m_i_impl.erl161
-rw-r--r--lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/my.c51
-rw-r--r--lib/ic/test/erl_client_c_server_SUITE.erl350
-rw-r--r--lib/ic/test/erl_client_c_server_SUITE_data/Makefile.src150
-rw-r--r--lib/ic/test/erl_client_c_server_SUITE_data/c_server.c299
-rw-r--r--lib/ic/test/erl_client_c_server_SUITE_data/callbacks.c610
-rw-r--r--lib/ic/test/erl_client_c_server_SUITE_data/erl_c_test.idl174
-rw-r--r--lib/ic/test/erl_client_c_server_SUITE_data/erl_client.erl331
-rw-r--r--lib/ic/test/erl_client_c_server_proto_SUITE.erl350
-rw-r--r--lib/ic/test/erl_client_c_server_proto_SUITE_data/Makefile.src150
-rw-r--r--lib/ic/test/erl_client_c_server_proto_SUITE_data/c_server.c299
-rw-r--r--lib/ic/test/erl_client_c_server_proto_SUITE_data/callbacks.c610
-rw-r--r--lib/ic/test/erl_client_c_server_proto_SUITE_data/erl_c_test.idl174
-rw-r--r--lib/ic/test/erl_client_c_server_proto_SUITE_data/erl_client.erl331
-rw-r--r--lib/ic/test/erl_client_c_server_proto_SUITE_data/my.c34
-rw-r--r--lib/ic/test/ic.spec1
-rw-r--r--lib/ic/test/ic.spec.vxworks2
-rw-r--r--lib/ic/test/ic_SUITE.erl973
-rw-r--r--lib/ic/test/ic_SUITE_data/Corba.idl1013
-rw-r--r--lib/ic/test/ic_SUITE_data/Coss.idl1537
-rw-r--r--lib/ic/test/ic_SUITE_data/attr.idl29
-rw-r--r--lib/ic/test/ic_SUITE_data/c_err1.idl63
-rw-r--r--lib/ic/test/ic_SUITE_data/c_err2.idl30
-rw-r--r--lib/ic/test/ic_SUITE_data/c_err3.idl28
-rw-r--r--lib/ic/test/ic_SUITE_data/c_norm.idl163
-rw-r--r--lib/ic/test/ic_SUITE_data/enum.idl32
-rw-r--r--lib/ic/test/ic_SUITE_data/forward.idl34
-rw-r--r--lib/ic/test/ic_SUITE_data/include.idl30
-rw-r--r--lib/ic/test/ic_SUITE_data/include2.idl26
-rw-r--r--lib/ic/test/ic_SUITE_data/include3.idl25
-rw-r--r--lib/ic/test/ic_SUITE_data/inherit.idl68
-rw-r--r--lib/ic/test/ic_SUITE_data/inherit_err.idl71
-rw-r--r--lib/ic/test/ic_SUITE_data/inherit_warn.idl64
-rw-r--r--lib/ic/test/ic_SUITE_data/mult_ids.idl92
-rw-r--r--lib/ic/test/ic_SUITE_data/nasty.idl60
-rw-r--r--lib/ic/test/ic_SUITE_data/one.idl29
-rw-r--r--lib/ic/test/ic_SUITE_data/one_followed.idl54
-rw-r--r--lib/ic/test/ic_SUITE_data/one_out.idl28
-rw-r--r--lib/ic/test/ic_SUITE_data/one_raises.idl32
-rw-r--r--lib/ic/test/ic_SUITE_data/one_void.idl30
-rw-r--r--lib/ic/test/ic_SUITE_data/raises_reg.idl52
-rw-r--r--lib/ic/test/ic_SUITE_data/struct.idl53
-rw-r--r--lib/ic/test/ic_SUITE_data/syntax1.idl28
-rw-r--r--lib/ic/test/ic_SUITE_data/syntax2.idl27
-rw-r--r--lib/ic/test/ic_SUITE_data/syntax3.idl20
-rw-r--r--lib/ic/test/ic_SUITE_data/syntax4.idl23
-rw-r--r--lib/ic/test/ic_SUITE_data/syntax5.idl22
-rw-r--r--lib/ic/test/ic_SUITE_data/syntax6.idl20
-rw-r--r--lib/ic/test/ic_SUITE_data/type.idl190
-rw-r--r--lib/ic/test/ic_SUITE_data/typeid.idl28
-rw-r--r--lib/ic/test/ic_SUITE_data/u_case_mult.idl54
-rw-r--r--lib/ic/test/ic_SUITE_data/u_default.idl51
-rw-r--r--lib/ic/test/ic_SUITE_data/u_mult.idl61
-rw-r--r--lib/ic/test/ic_SUITE_data/u_norm.idl63
-rw-r--r--lib/ic/test/ic_SUITE_data/u_type.idl82
-rw-r--r--lib/ic/test/ic_SUITE_data/undef_id.idl63
-rw-r--r--lib/ic/test/ic_be_SUITE.erl69
-rw-r--r--lib/ic/test/ic_be_SUITE_data/plain.idl33
-rw-r--r--lib/ic/test/ic_pp_SUITE.erl647
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/arg.idl38
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/cascade.idl29
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/comment.idl72
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/concat.idl60
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/define.idl41
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/if.idl32
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/if_zero.idl31
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/improp_nest_constr.idl30
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/inc.idl68
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/included1.idl35
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/included2.idl41
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/includer.idl45
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/line.idl45
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/misc.idl44
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/nopara.idl35
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/predef.idl33
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/predef_time.idl24
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/self_ref.idl26
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/separate.idl37
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/swallow_sc.idl37
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/unintended_grp.idl29
-rw-r--r--lib/ic/test/ic_pragma_SUITE.erl295
-rw-r--r--lib/ic/test/ic_pragma_SUITE_data/reg_m0.idl77
-rw-r--r--lib/ic/test/ic_pragma_SUITE_data/reg_m1.idl75
-rw-r--r--lib/ic/test/ic_pragma_SUITE_data/reg_m2.idl40
-rw-r--r--lib/ic/test/ic_pragma_SUITE_data/reg_m3.idl38
-rw-r--r--lib/ic/test/ic_pragma_SUITE_data/reg_m4.idl64
-rw-r--r--lib/ic/test/ic_pragma_SUITE_data/reg_m5.idl28
-rw-r--r--lib/ic/test/ic_pragma_SUITE_data/reg_m6.idl38
-rw-r--r--lib/ic/test/ic_pragma_SUITE_data/reg_m7.idl62
-rw-r--r--lib/ic/test/ic_pragma_SUITE_data/uggly.idl204
-rw-r--r--lib/ic/test/ic_register_SUITE.erl425
-rw-r--r--lib/ic/test/ic_register_SUITE_data/reg_m10.idl37
-rw-r--r--lib/ic/test/ic_register_SUITE_data/reg_m11.idl32
-rw-r--r--lib/ic/test/ic_register_SUITE_data/reg_m12.idl40
-rw-r--r--lib/ic/test/ic_register_SUITE_data/reg_m8.idl32
-rw-r--r--lib/ic/test/ic_register_SUITE_data/reg_m9.idl32
-rw-r--r--lib/ic/test/java_client_erl_server_SUITE.erl330
-rw-r--r--lib/ic/test/java_client_erl_server_SUITE_data/JavaClient.java759
-rw-r--r--lib/ic/test/java_client_erl_server_SUITE_data/Makefile.src88
-rw-r--r--lib/ic/test/java_client_erl_server_SUITE_data/java_erl_test.idl68
-rw-r--r--lib/ic/test/java_client_erl_server_SUITE_data/m_i_impl.erl169
-rw-r--r--lib/ic/vsn.mk19
-rw-r--r--lib/inets/doc/src/http_client.xml29
-rw-r--r--lib/inets/doc/src/inets.xml22
-rw-r--r--lib/inets/doc/src/notes.xml49
-rw-r--r--lib/inets/src/http_client/httpc_handler.erl23
-rw-r--r--lib/inets/src/http_client/httpc_manager.erl36
-rw-r--r--lib/inets/src/http_client/httpc_response.erl2
-rw-r--r--lib/inets/src/inets_app/inets.appup.src66
-rw-r--r--lib/inets/src/inets_app/inets.erl18
-rw-r--r--lib/inets/test/ftp_macosx_x86_test.erl6
-rw-r--r--lib/inets/test/ftp_suite_lib.erl26
-rw-r--r--lib/inets/test/httpc_SUITE.erl82
-rw-r--r--lib/inets/vsn.mk115
-rw-r--r--lib/inviso/doc/src/notes.xml18
-rw-r--r--lib/inviso/vsn.mk2
-rw-r--r--lib/jinterface/doc/src/notes.xml16
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpEpmd.java161
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java5
-rw-r--r--lib/jinterface/test/Makefile84
-rw-r--r--lib/jinterface/test/jinterface.dynspec32
-rw-r--r--lib/jinterface/test/jinterface_SUITE.erl761
-rw-r--r--lib/jinterface/test/jinterface_SUITE_data/BooleanAtom.java46
-rw-r--r--lib/jinterface/test/jinterface_SUITE_data/GetNames.java68
-rw-r--r--lib/jinterface/test/jinterface_SUITE_data/Makefile.src62
-rw-r--r--lib/jinterface/test/jinterface_SUITE_data/MboxLinkUnlink.java201
-rw-r--r--lib/jinterface/test/jinterface_SUITE_data/MboxPing.java50
-rw-r--r--lib/jinterface/test/jinterface_SUITE_data/MboxSendReceive.java229
-rw-r--r--lib/jinterface/test/jinterface_SUITE_data/NodePing.java83
-rw-r--r--lib/jinterface/test/jinterface_SUITE_data/NodeStatusHandler.java168
-rw-r--r--lib/jinterface/test/jinterface_SUITE_data/Nodename.java54
-rw-r--r--lib/jinterface/test/jinterface_SUITE_data/RegisterAndWhereis.java79
-rw-r--r--lib/jinterface/test/jitu.erl156
-rw-r--r--lib/jinterface/test/nc_SUITE.erl736
-rw-r--r--lib/jinterface/test/nc_SUITE_data/Makefile.src53
-rw-r--r--lib/jinterface/test/nc_SUITE_data/connection_server.java96
-rw-r--r--lib/jinterface/test/nc_SUITE_data/echo_server.java261
-rw-r--r--lib/jinterface/vsn.mk20
-rw-r--r--lib/kernel/doc/src/erl_ddll.xml38
-rw-r--r--lib/kernel/doc/src/gen_tcp.xml5
-rw-r--r--lib/kernel/doc/src/inet.xml63
-rw-r--r--lib/kernel/doc/src/notes.xml121
-rw-r--r--lib/kernel/src/erl_epmd.erl86
-rw-r--r--lib/kernel/src/erl_epmd.hrl17
-rw-r--r--lib/kernel/src/gen_sctp.erl38
-rw-r--r--lib/kernel/src/gen_tcp.erl36
-rw-r--r--lib/kernel/src/gen_udp.erl34
-rw-r--r--lib/kernel/src/inet.erl12
-rw-r--r--lib/kernel/src/inet6_sctp.erl23
-rw-r--r--lib/kernel/src/inet_config.erl2
-rw-r--r--lib/kernel/src/inet_int.hrl3
-rw-r--r--lib/kernel/src/inet_parse.erl2
-rw-r--r--lib/kernel/src/inet_sctp.erl21
-rw-r--r--lib/kernel/src/kernel.erl9
-rw-r--r--lib/kernel/src/net_kernel.erl4
-rw-r--r--lib/kernel/test/code_SUITE_data/on_load_app-1.0/src/on_load_embedded.erl9
-rw-r--r--lib/kernel/test/erl_distribution_SUITE.erl2
-rw-r--r--lib/kernel/test/gen_sctp_SUITE.erl244
-rw-r--r--lib/kernel/test/gen_tcp_api_SUITE.erl57
-rw-r--r--lib/kernel/test/gen_tcp_misc_SUITE.erl17
-rw-r--r--lib/kernel/test/gen_udp_SUITE.erl78
-rw-r--r--lib/kernel/test/inet_SUITE.erl153
-rw-r--r--lib/kernel/vsn.mk21
-rw-r--r--lib/megaco/doc/src/notes.xml17
-rw-r--r--lib/megaco/examples/meas/megaco_codec_meas.erl4
-rw-r--r--lib/megaco/examples/meas/megaco_codec_mstone_lib.erl4
-rw-r--r--lib/megaco/src/app/megaco.appup.src121
-rw-r--r--lib/megaco/src/binary/megaco_binary_transformer_prev3a.erl10
-rw-r--r--lib/megaco/src/binary/megaco_binary_transformer_prev3b.erl10
-rw-r--r--lib/megaco/src/binary/megaco_binary_transformer_prev3c.erl10
-rw-r--r--lib/megaco/src/binary/megaco_binary_transformer_v3.erl10
-rw-r--r--lib/megaco/src/engine/megaco_sdp.erl4
-rw-r--r--lib/megaco/src/text/megaco_text_gen_prev3a.hrl6
-rw-r--r--lib/megaco/src/text/megaco_text_gen_prev3b.hrl6
-rw-r--r--lib/megaco/src/text/megaco_text_gen_prev3c.hrl6
-rw-r--r--lib/megaco/src/text/megaco_text_gen_v1.hrl6
-rw-r--r--lib/megaco/src/text/megaco_text_gen_v2.hrl6
-rw-r--r--lib/megaco/src/text/megaco_text_gen_v3.hrl6
-rw-r--r--lib/megaco/vsn.mk149
-rw-r--r--lib/mnesia/doc/src/notes.xml17
-rw-r--r--lib/mnesia/src/mnesia_controller.erl2
-rw-r--r--lib/mnesia/src/mnesia_locker.erl2
-rw-r--r--lib/mnesia/src/mnesia_log.erl2
-rw-r--r--lib/mnesia/src/mnesia_monitor.erl2
-rw-r--r--lib/mnesia/src/mnesia_recover.erl1
-rw-r--r--lib/mnesia/src/mnesia_registry.erl4
-rw-r--r--lib/mnesia/src/mnesia_subscr.erl2
-rw-r--r--lib/mnesia/src/mnesia_text.erl4
-rw-r--r--lib/mnesia/test/Makefile2
-rw-r--r--lib/mnesia/vsn.mk18
-rw-r--r--lib/observer/src/Makefile3
-rw-r--r--lib/odbc/c_src/odbcserver.c100
-rw-r--r--lib/odbc/c_src/odbcserver.h1
-rw-r--r--lib/odbc/configure.in9
-rw-r--r--lib/odbc/src/odbc.erl6
-rw-r--r--lib/odbc/vsn.mk22
-rw-r--r--lib/orber/COSS/CosNaming/orber_cosnaming_utils.erl13
-rw-r--r--lib/orber/doc/src/notes.xml54
-rw-r--r--lib/orber/src/orber_tb.erl4
-rw-r--r--lib/orber/vsn.mk22
-rw-r--r--lib/os_mon/test/Makefile92
-rw-r--r--lib/os_mon/test/cpu_sup_SUITE.erl282
-rw-r--r--lib/os_mon/test/disksup_SUITE.erl426
-rw-r--r--lib/os_mon/test/memsup_SUITE.erl782
-rw-r--r--lib/os_mon/test/os_mon.spec1
-rw-r--r--lib/os_mon/test/os_mon_SUITE.erl89
-rw-r--r--lib/os_mon/test/os_mon_conf.erl28
-rw-r--r--lib/os_mon/test/os_mon_mib_SUITE.erl746
-rw-r--r--lib/os_mon/test/os_sup_SUITE.erl189
-rw-r--r--lib/parsetools/doc/src/notes.xml15
-rw-r--r--lib/parsetools/include/yeccpre.hrl26
-rw-r--r--lib/parsetools/src/yecc.erl18
-rw-r--r--lib/parsetools/src/yeccparser.erl215
-rw-r--r--lib/parsetools/test/yecc_SUITE.erl28
-rw-r--r--lib/parsetools/vsn.mk2
-rw-r--r--lib/public_key/asn1/OTP-PKIX.asn113
-rw-r--r--lib/public_key/doc/src/cert_records.xml37
-rw-r--r--lib/public_key/doc/src/notes.xml94
-rw-r--r--lib/public_key/doc/src/public_key.xml500
-rw-r--r--lib/public_key/include/public_key.hrl24
-rw-r--r--lib/public_key/src/Makefile3
-rw-r--r--lib/public_key/src/pubkey_cert.erl559
-rw-r--r--lib/public_key/src/pubkey_cert_records.erl86
-rw-r--r--lib/public_key/src/pubkey_crypto.erl171
-rw-r--r--lib/public_key/src/pubkey_pem.erl250
-rw-r--r--lib/public_key/src/public_key.app.src1
-rw-r--r--lib/public_key/src/public_key.appup.src26
-rw-r--r--lib/public_key/src/public_key.erl767
-rw-r--r--lib/public_key/test/Makefile2
-rw-r--r--lib/public_key/test/erl_make_certs.erl (renamed from lib/public_key/test/pkey_test.erl)87
-rw-r--r--lib/public_key/test/pkits_SUITE.erl6
-rw-r--r--lib/public_key/test/public_key_SUITE.erl354
-rw-r--r--lib/public_key/vsn.mk12
-rw-r--r--lib/reltool/test/Makefile3
-rw-r--r--lib/reltool/vsn.mk27
-rw-r--r--lib/runtime_tools/c_src/trace_file_drv.c2
-rw-r--r--lib/runtime_tools/doc/src/notes.xml21
-rw-r--r--lib/runtime_tools/src/inviso_autostart.erl11
-rw-r--r--lib/runtime_tools/src/inviso_autostart_server.erl12
-rw-r--r--lib/runtime_tools/test/Makefile65
-rw-r--r--lib/runtime_tools/test/dbg_SUITE.erl901
-rw-r--r--lib/runtime_tools/test/dbg_SUITE_data/dbg_test.erl87
-rw-r--r--lib/runtime_tools/test/dbg_SUITE_data/exref_td.erl50
-rw-r--r--lib/runtime_tools/test/erts_alloc_config_SUITE.erl206
-rw-r--r--lib/runtime_tools/test/inviso_SUITE.erl2840
-rw-r--r--lib/runtime_tools/test/inviso_testmodule1_foo.erl9
-rw-r--r--lib/runtime_tools/test/runtime_tools.cover1
-rw-r--r--lib/runtime_tools/test/runtime_tools.spec1
-rw-r--r--lib/runtime_tools/test/runtime_tools_SUITE.erl50
-rw-r--r--lib/runtime_tools/vsn.mk2
-rw-r--r--lib/snmp/doc/src/notes.xml48
-rw-r--r--lib/snmp/examples/ex2/snmp_ex2_manager.erl4
-rw-r--r--lib/snmp/examples/ex2/snmp_ex2_simple_standard_test.erl4
-rw-r--r--lib/snmp/src/agent/snmp_community_mib.erl4
-rw-r--r--lib/snmp/src/agent/snmp_framework_mib.erl4
-rw-r--r--lib/snmp/src/agent/snmp_generic.erl4
-rw-r--r--lib/snmp/src/agent/snmp_notification_mib.erl4
-rw-r--r--lib/snmp/src/agent/snmp_standard_mib.erl4
-rw-r--r--lib/snmp/src/agent/snmp_target_mib.erl4
-rw-r--r--lib/snmp/src/agent/snmp_user_based_sm_mib.erl4
-rw-r--r--lib/snmp/src/agent/snmp_view_based_acm_mib.erl4
-rw-r--r--lib/snmp/src/agent/snmpa_conf.erl4
-rw-r--r--lib/snmp/src/agent/snmpa_net_if.erl11
-rw-r--r--lib/snmp/src/agent/snmpa_target_cache.erl4
-rw-r--r--lib/snmp/src/agent/snmpa_usm.erl4
-rw-r--r--lib/snmp/src/app/snmp.appup.src298
-rw-r--r--lib/snmp/src/compile/snmpc_lib.erl2
-rw-r--r--lib/snmp/src/manager/snmpm.erl4
-rw-r--r--lib/snmp/src/manager/snmpm_conf.erl4
-rw-r--r--lib/snmp/src/manager/snmpm_config.erl2
-rw-r--r--lib/snmp/src/manager/snmpm_usm.erl6
-rw-r--r--lib/snmp/src/misc/snmp_conf.erl4
-rw-r--r--lib/snmp/src/misc/snmp_config.erl2
-rw-r--r--lib/snmp/src/misc/snmp_usm.erl2
-rw-r--r--lib/snmp/vsn.mk56
-rw-r--r--lib/ssh/doc/src/notes.xml76
-rw-r--r--lib/ssh/src/ssh.appup.src6
-rw-r--r--lib/ssh/src/ssh_channel.erl14
-rw-r--r--lib/ssh/src/ssh_cli.erl28
-rw-r--r--lib/ssh/src/ssh_connection_controler.erl4
-rw-r--r--lib/ssh/src/ssh_connection_handler.erl16
-rw-r--r--lib/ssh/src/ssh_connection_manager.erl23
-rwxr-xr-xlib/ssh/src/ssh_file.erl17
-rw-r--r--lib/ssh/src/ssh_system_sup.erl20
-rw-r--r--lib/ssh/vsn.mk81
-rw-r--r--lib/ssl/Makefile16
-rw-r--r--lib/ssl/doc/src/notes.xml151
-rw-r--r--lib/ssl/doc/src/ssl.xml298
-rw-r--r--lib/ssl/doc/src/ssl_distribution.xml10
-rw-r--r--lib/ssl/doc/src/ssl_protocol.xml12
-rw-r--r--lib/ssl/doc/src/ssl_session_cache_api.xml20
-rw-r--r--lib/ssl/examples/certs/Makefile41
-rw-r--r--lib/ssl/examples/certs/Makefile.in80
-rw-r--r--lib/ssl/examples/certs/ebin/.gitignore0
-rw-r--r--lib/ssl/examples/certs/etc/client/cacerts.pem34
-rw-r--r--lib/ssl/examples/certs/etc/client/cert.pem17
-rw-r--r--lib/ssl/examples/certs/etc/client/key.pem16
-rw-r--r--lib/ssl/examples/certs/etc/erlangCA/cert.pem17
-rw-r--r--lib/ssl/examples/certs/etc/otpCA/cert.pem17
-rw-r--r--lib/ssl/examples/certs/etc/server/cacerts.pem34
-rw-r--r--lib/ssl/examples/certs/etc/server/cert.pem17
-rw-r--r--lib/ssl/examples/certs/etc/server/key.pem16
-rw-r--r--lib/ssl/examples/certs/rnd/RANDbin512 -> 0 bytes
-rw-r--r--lib/ssl/examples/certs/src/make_certs.erl297
-rw-r--r--lib/ssl/src/ssl.appup.src25
-rw-r--r--lib/ssl/src/ssl.erl325
-rw-r--r--lib/ssl/src/ssl_app.erl4
-rw-r--r--lib/ssl/src/ssl_certificate.erl101
-rw-r--r--lib/ssl/src/ssl_certificate_db.erl54
-rw-r--r--lib/ssl/src/ssl_cipher.erl96
-rw-r--r--lib/ssl/src/ssl_cipher.hrl2
-rw-r--r--lib/ssl/src/ssl_connection.erl399
-rw-r--r--lib/ssl/src/ssl_handshake.erl476
-rw-r--r--lib/ssl/src/ssl_internal.hrl13
-rw-r--r--lib/ssl/src/ssl_manager.erl58
-rw-r--r--lib/ssl/src/ssl_record.erl108
-rw-r--r--lib/ssl/src/ssl_session.erl6
-rw-r--r--lib/ssl/src/ssl_ssl3.erl14
-rw-r--r--lib/ssl/src/ssl_sup.erl7
-rw-r--r--lib/ssl/src/ssl_tls1.erl7
-rw-r--r--lib/ssl/test/Makefile1
-rw-r--r--lib/ssl/test/erl_make_certs.erl85
-rw-r--r--lib/ssl/test/make_certs.erl16
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl647
-rw-r--r--lib/ssl/test/ssl_packet_SUITE.erl373
-rw-r--r--lib/ssl/test/ssl_session_cache_SUITE.erl305
-rw-r--r--lib/ssl/test/ssl_test_lib.erl55
-rw-r--r--lib/ssl/test/ssl_to_openssl_SUITE.erl38
-rw-r--r--lib/ssl/vsn.mk63
-rw-r--r--lib/stdlib/doc/src/dets.xml4
-rw-r--r--lib/stdlib/doc/src/erl_id_trans.xml5
-rw-r--r--lib/stdlib/doc/src/erl_lint.xml4
-rw-r--r--lib/stdlib/doc/src/erl_parse.xml2
-rw-r--r--lib/stdlib/doc/src/ets.xml129
-rw-r--r--lib/stdlib/doc/src/filelib.xml8
-rw-r--r--lib/stdlib/doc/src/io_protocol.xml2
-rw-r--r--lib/stdlib/doc/src/lists.xml6
-rw-r--r--lib/stdlib/doc/src/notes.xml136
-rw-r--r--lib/stdlib/doc/src/supervisor.xml2
-rw-r--r--lib/stdlib/doc/src/sys.xml2
-rw-r--r--lib/stdlib/src/beam_lib.erl4
-rw-r--r--lib/stdlib/src/c.erl2
-rw-r--r--lib/stdlib/src/dets.erl111
-rw-r--r--lib/stdlib/src/dets_v8.erl2
-rw-r--r--lib/stdlib/src/dets_v9.erl5
-rw-r--r--lib/stdlib/src/digraph.erl2
-rw-r--r--lib/stdlib/src/epp.erl43
-rw-r--r--lib/stdlib/src/erl_internal.erl8
-rw-r--r--lib/stdlib/src/erl_lint.erl14
-rw-r--r--lib/stdlib/src/eval_bits.erl4
-rw-r--r--lib/stdlib/src/file_sorter.erl2
-rw-r--r--lib/stdlib/src/filelib.erl2
-rw-r--r--lib/stdlib/src/gb_sets.erl2
-rw-r--r--lib/stdlib/src/lists.erl68
-rw-r--r--lib/stdlib/src/ms_transform.erl193
-rw-r--r--lib/stdlib/src/orddict.erl2
-rw-r--r--lib/stdlib/src/ordsets.erl18
-rw-r--r--lib/stdlib/src/otp_internal.erl6
-rw-r--r--lib/stdlib/src/qlc.erl2
-rw-r--r--lib/stdlib/src/string.erl2
-rw-r--r--lib/stdlib/src/supervisor.erl14
-rw-r--r--lib/stdlib/src/timer.erl3
-rw-r--r--lib/stdlib/test/dets_SUITE.erl145
-rw-r--r--lib/stdlib/test/epp_SUITE.erl38
-rw-r--r--lib/stdlib/test/escript_SUITE.erl15
-rwxr-xr-xlib/stdlib/test/escript_SUITE_data/arg_overflow5
-rwxr-xr-xlib/stdlib/test/escript_SUITE_data/linebuf_overflow5
-rw-r--r--lib/stdlib/test/ets_SUITE.erl75
-rw-r--r--lib/stdlib/test/ms_transform_SUITE.erl101
-rw-r--r--lib/stdlib/test/string_SUITE.erl5
-rw-r--r--lib/stdlib/vsn.mk21
-rw-r--r--lib/syntax_tools/src/epp_dodger.erl2
-rw-r--r--lib/syntax_tools/src/erl_prettypr.erl16
-rw-r--r--lib/syntax_tools/src/erl_recomment.erl5
-rw-r--r--lib/syntax_tools/src/erl_syntax.erl4
-rw-r--r--lib/syntax_tools/src/erl_syntax_lib.erl32
-rw-r--r--lib/syntax_tools/src/erl_tidy.erl15
-rw-r--r--lib/syntax_tools/src/igor.erl52
-rw-r--r--lib/test_server/doc/src/notes.xml42
-rw-r--r--lib/test_server/src/Makefile2
-rw-r--r--lib/test_server/src/test_server.erl9
-rw-r--r--lib/test_server/src/test_server_ctrl.erl93
-rw-r--r--lib/test_server/src/ts_install.erl8
-rw-r--r--lib/test_server/src/ts_lib.erl2
-rw-r--r--lib/test_server/src/ts_reports.erl4
-rw-r--r--lib/test_server/test/Makefile2
-rw-r--r--lib/tools/doc/src/erlang_mode.xml2
-rw-r--r--lib/tools/doc/src/erlang_mode_chapter.xml2
-rw-r--r--lib/tools/doc/src/notes.xml16
-rw-r--r--lib/tools/emacs/erlang.el18
-rw-r--r--lib/tools/src/cover.erl2
-rw-r--r--lib/tools/src/xref_base.erl2
-rw-r--r--lib/tools/src/xref_compiler.erl2
-rw-r--r--lib/tools/src/xref_utils.erl2
-rw-r--r--lib/tools/vsn.mk20
-rw-r--r--lib/tv/doc/src/notes.xml17
-rw-r--r--lib/tv/vsn.mk21
-rw-r--r--lib/typer/src/typer.erl4
-rw-r--r--lib/typer/vsn.mk2
-rw-r--r--lib/wx/.gitignore2
-rw-r--r--lib/wx/api_gen/wxapi.conf9
-rw-r--r--lib/wx/c_src/gen/wxe_derived_dest.h2
-rw-r--r--lib/wx/c_src/gen/wxe_events.cpp46
-rw-r--r--lib/wx/c_src/gen/wxe_funcs.cpp41
-rw-r--r--lib/wx/c_src/gen/wxe_macros.h2883
-rw-r--r--lib/wx/c_src/wxe_impl.cpp4
-rwxr-xr-xlib/wx/configure.in41
-rw-r--r--lib/wx/doc/src/notes.xml29
-rw-r--r--lib/wx/src/gen/wxTreeCtrl.erl10
-rw-r--r--lib/wx/src/gen/wxe_debug.hrl2883
-rw-r--r--lib/wx/src/gen/wxe_funcs.hrl2883
-rw-r--r--lib/wx/test/Makefile2
-rw-r--r--lib/wx/test/wx_class_SUITE.erl3
-rw-r--r--lib/wx/vsn.mk10
-rw-r--r--lib/xmerl/doc/src/notes.xml19
-rw-r--r--lib/xmerl/src/xmerl_dtd.erl0
-rw-r--r--lib/xmerl/src/xmerl_scan.erl33
-rw-r--r--lib/xmerl/vsn.mk131
-rw-r--r--make/emd2exml.in1
-rw-r--r--make/otp.mk.in5
-rwxr-xr-xotp_build2
-rw-r--r--system/doc/Books/src/HOWTO.txt35
-rw-r--r--system/doc/Books/src/Makefile127
-rw-r--r--system/doc/Books/src/basic_application.xml107
-rw-r--r--system/doc/Books/src/corba_service.xml137
-rw-r--r--system/doc/Books/src/database_management.xml118
-rw-r--r--system/doc/Books/src/frame_crop.header.src101
-rw-r--r--system/doc/Books/src/insidecover.xml35
-rw-r--r--system/doc/Books/src/interfaces.xml144
-rwxr-xr-xsystem/doc/Books/src/make_headers30
-rw-r--r--system/doc/Books/src/operation_maintenance.xml94
-rw-r--r--system/doc/Books/src/orber_ic.xml112
-rw-r--r--system/doc/Books/src/stdlib.xml73
-rw-r--r--system/doc/Books/src/tools.xml139
-rw-r--r--system/doc/Books/src/ug.xml127
-rwxr-xr-xsystem/doc/reference_manual/typespec.xml659
-rw-r--r--system/doc/top/Makefile31
-rw-r--r--system/doc/top/src/erl_html_tools.erl92
-rw-r--r--system/doc/top/src/otp_man_index.erl75
-rw-r--r--system/doc/top/templates/index.html.src4
-rw-r--r--system/doc/tutorial/c_port.xmlsrc2
837 files changed, 75562 insertions, 21895 deletions
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000000..596615322f
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+.gitattributes export-ignore
+.gitignore export-ignore
diff --git a/.gitignore b/.gitignore
index aa32bd9582..6034a21f87 100644
--- a/.gitignore
+++ b/.gitignore
@@ -33,6 +33,7 @@ a.out.dSYM/
/config.status
/bootstrap/bin/*
+/bootstrap/target
!/bootstrap/bin/*.script
!/bootstrap/bin/*.boot
@@ -142,6 +143,7 @@ a.out.dSYM/
/erts/doc/pdf/*.fo
/erts/doc/pdf/*.pdf
/erts/doc/man[0-9]/*.[0-9]
+/erts/doc/CONF_INFO
# et
@@ -189,6 +191,11 @@ a.out.dSYM/
/lib/kernel/src/inet_dns_record_adts.hrl
+# kernel
+
+/lib/mnesia/test/Mnesia.*
+/lib/mnesia/test/test_log*
+
# otp_mibs
/lib/otp_mibs/include/[A-Z]*.hrl
@@ -219,9 +226,6 @@ a.out.dSYM/
# ssl
/lib/ssl/pkix/*.asn1db
-/lib/ssl/examples/certs/done
-/lib/ssl/examples/certs/ebin/make_certs.beam
-/lib/ssl/examples/certs/etc/
/lib/ssl/include/OTP-PKIX.hrl
/lib/ssl/pkix/OTP-PKIX.erl
/lib/ssl/pkix/OTP-PKIX.hrl
@@ -261,6 +265,8 @@ a.out.dSYM/
/system/doc/tutorial/cnode.xml
/system/doc/tutorial/erl_interface.xml
/system/doc/tutorial/example.xml
+/system/doc/tutorial/nif.xml
+/system/doc/html/installation_guide
/system/doc/installation_guide/INSTALL.xml
/system/doc/installation_guide/INSTALL-CROSS.xml
/system/doc/installation_guide/INSTALL-WIN32.xml
diff --git a/INSTALL.md b/INSTALL.md
index 2567b791e5..1061c5187a 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -277,7 +277,8 @@ Some of the available `configure` options are:
x86 processors before pentium 4 (back to 486) in the ethread library. If
not passed the ethread library (part of the runtime system) will use
instructions that first appeared on the pentium 4 processor when building
- for x86.
+ for x86. This option will be automatically enabled if required on the
+ build machine.
* `--with-libatomic_ops=PATH` - Use the `libatomic_ops` library for atomic
memory accesses. If `configure` should inform you about no native atomic
implementation available, you typically want to try using the
diff --git a/README.bootstrap b/README.bootstrap
index b0c8a1cc20..f42bc7aa47 100644
--- a/README.bootstrap
+++ b/README.bootstrap
@@ -45,13 +45,11 @@ preloaded files are to be updated, the source code is built using a
special Makefile in the $ERL_TOP/preloaded/src directory, which
creates beam files in the same directory. When they seem to compile
successfully, they can be used in an emulator build by being copied
-to the ebin directory (although, in Clearcase that requires checking
-out the files in the ebin directory first). For developers using the
-main Clearcase branch, otp_build {prepare,update,commit}_preloaded can
-be used to ease the process (there are also similar targets in the
+to the ebin directory. otp_build update_preloaded can be used to
+ease the process (there are also similar targets in the
$ERL_TOP/preloaded/src/Makefile).
-In prebuilt open source distributions, these .beam files are also
+In prebuilt open source distributions, these beam files are also
present, but to update them one might need to change permission on the
$ERL_TOP/preloaded/ebin directory, then build and then manually copy
the beam files from the source directory to ../ebin. If patches are
@@ -60,4 +58,4 @@ always note this specially as the preloaded/ebin directory needs
updating, or provide the new derived files in the patch or as complete
binaries.
-/Patrik, OTP \ No newline at end of file
+/Patrik, OTP
diff --git a/bootstrap/bin/start.boot b/bootstrap/bin/start.boot
index e09d7405b2..c7f5785eee 100644
--- a/bootstrap/bin/start.boot
+++ b/bootstrap/bin/start.boot
Binary files differ
diff --git a/bootstrap/bin/start.script b/bootstrap/bin/start.script
index 7a62fabed4..3f472b5e8c 100644
--- a/bootstrap/bin/start.script
+++ b/bootstrap/bin/start.script
@@ -1,6 +1,6 @@
-%% script generated at {2010,8,3} {17,6,26}
+%% script generated at {2010,10,18} {14,19,26}
{script,
- {"OTP APN 181 01","R14B"},
+ {"OTP APN 181 01","R14B01"},
[{preLoaded,
[erl_prim_loader,erlang,init,otp_ring0,prim_file,prim_inet,prim_zip,
zlib]},
@@ -43,7 +43,7 @@
{application_controller,start,
[{application,kernel,
[{description,"ERTS CXC 138 10"},
- {vsn,"2.14.1"},
+ {vsn,"2.14.2"},
{id,[]},
{modules,
[application,application_controller,application_master,
@@ -80,7 +80,7 @@
{application,load,
[{application,stdlib,
[{description,"ERTS CXC 138 10"},
- {vsn,"1.17.1"},
+ {vsn,"1.17.2"},
{id,[]},
{modules,
[array,base64,beam_lib,binary,c,calendar,dets,
diff --git a/bootstrap/bin/start_clean.boot b/bootstrap/bin/start_clean.boot
index e09d7405b2..c7f5785eee 100644
--- a/bootstrap/bin/start_clean.boot
+++ b/bootstrap/bin/start_clean.boot
Binary files differ
diff --git a/bootstrap/bin/start_clean.script b/bootstrap/bin/start_clean.script
index 7a62fabed4..3f472b5e8c 100644
--- a/bootstrap/bin/start_clean.script
+++ b/bootstrap/bin/start_clean.script
@@ -1,6 +1,6 @@
-%% script generated at {2010,8,3} {17,6,26}
+%% script generated at {2010,10,18} {14,19,26}
{script,
- {"OTP APN 181 01","R14B"},
+ {"OTP APN 181 01","R14B01"},
[{preLoaded,
[erl_prim_loader,erlang,init,otp_ring0,prim_file,prim_inet,prim_zip,
zlib]},
@@ -43,7 +43,7 @@
{application_controller,start,
[{application,kernel,
[{description,"ERTS CXC 138 10"},
- {vsn,"2.14.1"},
+ {vsn,"2.14.2"},
{id,[]},
{modules,
[application,application_controller,application_master,
@@ -80,7 +80,7 @@
{application,load,
[{application,stdlib,
[{description,"ERTS CXC 138 10"},
- {vsn,"1.17.1"},
+ {vsn,"1.17.2"},
{id,[]},
{modules,
[array,base64,beam_lib,binary,c,calendar,dets,
diff --git a/bootstrap/lib/compiler/ebin/beam_asm.beam b/bootstrap/lib/compiler/ebin/beam_asm.beam
index 75c6383ba3..7a40486b42 100644
--- a/bootstrap/lib/compiler/ebin/beam_asm.beam
+++ b/bootstrap/lib/compiler/ebin/beam_asm.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_block.beam b/bootstrap/lib/compiler/ebin/beam_block.beam
index 4d71b65e23..41be7667fc 100644
--- a/bootstrap/lib/compiler/ebin/beam_block.beam
+++ b/bootstrap/lib/compiler/ebin/beam_block.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_validator.beam b/bootstrap/lib/compiler/ebin/beam_validator.beam
index 6af598519f..32e75091f4 100644
--- a/bootstrap/lib/compiler/ebin/beam_validator.beam
+++ b/bootstrap/lib/compiler/ebin/beam_validator.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/compile.beam b/bootstrap/lib/compiler/ebin/compile.beam
index b460c83ba0..d9b955baff 100644
--- a/bootstrap/lib/compiler/ebin/compile.beam
+++ b/bootstrap/lib/compiler/ebin/compile.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/compiler.app b/bootstrap/lib/compiler/ebin/compiler.app
index d201d5fd0d..3fd5add16b 100644
--- a/bootstrap/lib/compiler/ebin/compiler.app
+++ b/bootstrap/lib/compiler/ebin/compiler.app
@@ -18,7 +18,7 @@
{application, compiler,
[{description, "ERTS CXC 138 10"},
- {vsn, "4.7"},
+ {vsn, "4.7.1"},
{modules, [
beam_asm,
beam_block,
diff --git a/bootstrap/lib/compiler/ebin/compiler.appup b/bootstrap/lib/compiler/ebin/compiler.appup
index 99b234c847..10c9fd3dde 100644
--- a/bootstrap/lib/compiler/ebin/compiler.appup
+++ b/bootstrap/lib/compiler/ebin/compiler.appup
@@ -1 +1 @@
-{"4.6.5",[],[]}.
+{"4.7.1",[],[]}.
diff --git a/bootstrap/lib/compiler/ebin/core_lint.beam b/bootstrap/lib/compiler/ebin/core_lint.beam
index e7db1d3f72..813c444d9c 100644
--- a/bootstrap/lib/compiler/ebin/core_lint.beam
+++ b/bootstrap/lib/compiler/ebin/core_lint.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/core_parse.beam b/bootstrap/lib/compiler/ebin/core_parse.beam
index 631c5d6aba..5e39a05dc5 100644
--- a/bootstrap/lib/compiler/ebin/core_parse.beam
+++ b/bootstrap/lib/compiler/ebin/core_parse.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/v3_codegen.beam b/bootstrap/lib/compiler/ebin/v3_codegen.beam
index 5555d01b2a..7cdb5fe92a 100644
--- a/bootstrap/lib/compiler/ebin/v3_codegen.beam
+++ b/bootstrap/lib/compiler/ebin/v3_codegen.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/v3_core.beam b/bootstrap/lib/compiler/ebin/v3_core.beam
index 5d889ea4f3..7a60d7b23d 100644
--- a/bootstrap/lib/compiler/ebin/v3_core.beam
+++ b/bootstrap/lib/compiler/ebin/v3_core.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/egen/core_parse.erl b/bootstrap/lib/compiler/egen/core_parse.erl
index b7f5579763..0e94fb414d 100644
--- a/bootstrap/lib/compiler/egen/core_parse.erl
+++ b/bootstrap/lib/compiler/egen/core_parse.erl
@@ -13,7 +13,7 @@
tok_val(T) -> element(3, T).
tok_line(T) -> element(2, T).
--file("/usr/local/otp_product/releases/sles10_32_R14A_patched/lib/parsetools-2.0.3/include/yeccpre.hrl", 0).
+-file("/usr/local/otp/releases/sles10_32_R14B_patched/lib/parsetools-2.0.4/include/yeccpre.hrl", 0).
%%
%% %CopyrightBegin%
%%
@@ -42,8 +42,8 @@ tok_line(T) -> element(2, T).
parse(Tokens) ->
yeccpars0(Tokens, {no_func, no_line}, 0, [], []).
--spec parse_and_scan({function() | {atom(), atom()}, [_]} | {atom(), atom(), [_]}) ->
- yecc_ret().
+-spec parse_and_scan({function() | {atom(), atom()}, [_]}
+ | {atom(), atom(), [_]}) -> yecc_ret().
parse_and_scan({F, A}) -> % Fun or {M, F}
yeccpars0([], {{F, A}, no_line}, 0, [], []);
parse_and_scan({M, F, A}) ->
@@ -60,7 +60,7 @@ format_error(Message) ->
%% To be used in grammar files to throw an error message to the parser
%% toplevel. Doesn't have to be exported!
--compile({nowarn_unused_function,{return_error,2}}).
+-compile({nowarn_unused_function, return_error/2}).
-spec return_error(integer(), any()) -> no_return().
return_error(Line, Message) ->
throw({error, {Line, ?MODULE, Message}}).
@@ -73,10 +73,7 @@ yeccpars0(Tokens, Tzr, State, States, Vstack) ->
error: Error ->
Stacktrace = erlang:get_stacktrace(),
try yecc_error_type(Error, Stacktrace) of
- {syntax_error, Token} ->
- yeccerror(Token);
- {missing_in_goto_table=Tag, Symbol, State} ->
- Desc = {Symbol, State, Tag},
+ Desc ->
erlang:raise(error, {yecc_bug, ?CODE_VERSION, Desc},
Stacktrace)
catch _:_ -> erlang:raise(error, Error, Stacktrace)
@@ -86,13 +83,15 @@ yeccpars0(Tokens, Tzr, State, States, Vstack) ->
Error
end.
-yecc_error_type(function_clause, [{?MODULE,F,[State,_,_,_,Token,_,_]} | _]) ->
+yecc_error_type(function_clause, [{?MODULE,F,ArityOrArgs} | _]) ->
case atom_to_list(F) of
- "yeccpars2" ++ _ ->
- {syntax_error, Token};
"yeccgoto_" ++ SymbolL ->
{ok,[{atom,_,Symbol}],_} = erl_scan:string(SymbolL),
- {missing_in_goto_table, Symbol, State}
+ State = case ArityOrArgs of
+ [S,_,_,_,_,_,_] -> S;
+ _ -> state_is_unknown
+ end,
+ {Symbol, State, missing_in_goto_table}
end.
yeccpars1([Token | Tokens], Tzr, State, States, Vstack) ->
@@ -157,11 +156,13 @@ yecctoken_end_location(Token) ->
yecctoken_location(Token)
end.
+-compile({nowarn_unused_function, yeccerror/1}).
yeccerror(Token) ->
Text = yecctoken_to_string(Token),
Location = yecctoken_location(Token),
{error, {Location, ?MODULE, ["syntax error before: ", Text]}}.
+-compile({nowarn_unused_function, yecctoken_to_string/1}).
yecctoken_to_string(Token) ->
case catch erl_scan:token_info(Token, text) of
{text, Txt} -> Txt;
@@ -174,6 +175,7 @@ yecctoken_location(Token) ->
_ -> element(2, Token)
end.
+-compile({nowarn_unused_function, yecctoken2string/1}).
yecctoken2string({atom, _, A}) -> io_lib:write(A);
yecctoken2string({integer,_,N}) -> io_lib:write(N);
yecctoken2string({float,_,F}) -> io_lib:write(F);
@@ -194,7 +196,7 @@ yecctoken2string(Other) ->
--file("/ldisk/bjorn/otp/bootstrap/lib/compiler/egen/core_parse.erl", 197).
+-file("/ldisk/bjorn/otp/bootstrap/lib/compiler/egen/core_parse.erl", 199).
yeccpars2(0=S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_0(S, Cat, Ss, Stack, T, Ts, Tzr);
@@ -845,38 +847,54 @@ yeccpars2(321=S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2(323=S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_323(S, Cat, Ss, Stack, T, Ts, Tzr);
yeccpars2(Other, _, _, _, _, _, _) ->
- erlang:error({yecc_bug,"1.3",{missing_state_in_action_table, Other}}).
+ erlang:error({yecc_bug,"1.4",{missing_state_in_action_table, Other}}).
yeccpars2_0(S, '(', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 2, Ss, Stack, T, Ts, Tzr);
yeccpars2_0(S, module, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 3, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 3, Ss, Stack, T, Ts, Tzr);
+yeccpars2_0(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_1(_S, '$end', _Ss, Stack, _T, _Ts, _Tzr) ->
- {ok, hd(Stack)}.
+ {ok, hd(Stack)};
+yeccpars2_1(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_2(S, module, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 315, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 315, Ss, Stack, T, Ts, Tzr);
+yeccpars2_2(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_3(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 4, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 4, Ss, Stack, T, Ts, Tzr);
+yeccpars2_3(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_4(S, '[', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 6, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 6, Ss, Stack, T, Ts, Tzr);
+yeccpars2_4(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_5(S, attributes, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 18, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 18, Ss, Stack, T, Ts, Tzr);
+yeccpars2_5(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_6(S, ']', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 10, Ss, Stack, T, Ts, Tzr);
yeccpars2_6(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 11, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 11, Ss, Stack, T, Ts, Tzr);
+yeccpars2_6(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_7(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_exported_name(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_8(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 16, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 16, Ss, Stack, T, Ts, Tzr);
+yeccpars2_8(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_9(S, ',', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 14, Ss, Stack, T, Ts, Tzr);
@@ -890,10 +908,14 @@ yeccpars2_10(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_module_export(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_11(S, '/', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 12, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 12, Ss, Stack, T, Ts, Tzr);
+yeccpars2_11(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_12(S, integer, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 13, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 13, Ss, Stack, T, Ts, Tzr);
+yeccpars2_12(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_13(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -901,7 +923,9 @@ yeccpars2_13(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_function_name(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_14(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 11, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 11, Ss, Stack, T, Ts, Tzr);
+yeccpars2_14(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -922,15 +946,21 @@ yeccpars2_17(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_58(_S, Cat, [17 | Ss], NewStack, T, Ts, Tzr).
yeccpars2_18(S, '[', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 19, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 19, Ss, Stack, T, Ts, Tzr);
+yeccpars2_18(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_19(S, ']', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 22, Ss, Stack, T, Ts, Tzr);
yeccpars2_19(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 23, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 23, Ss, Stack, T, Ts, Tzr);
+yeccpars2_19(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_20(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 55, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 55, Ss, Stack, T, Ts, Tzr);
+yeccpars2_20(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_21(S, ',', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 53, Ss, Stack, T, Ts, Tzr);
@@ -944,7 +974,9 @@ yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_module_attribute(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_23(S, '=', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 24, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 24, Ss, Stack, T, Ts, Tzr);
+yeccpars2_23(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_24(S, '[', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 30, Ss, Stack, T, Ts, Tzr);
@@ -962,7 +994,9 @@ yeccpars2_cont_24(S, float, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_cont_24(S, integer, Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 34, Ss, Stack, T, Ts, Tzr);
yeccpars2_cont_24(S, string, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 35, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 35, Ss, Stack, T, Ts, Tzr);
+yeccpars2_cont_24(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_literal(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
@@ -1025,7 +1059,9 @@ yeccpars2_36(S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_cont_24(S, Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_37(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 42, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 42, Ss, Stack, T, Ts, Tzr);
+yeccpars2_37(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_38(S, ',', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 40, Ss, Stack, T, Ts, Tzr);
@@ -1055,7 +1091,9 @@ yeccpars2_43(S, ',', Ss, Stack, T, Ts, Tzr) ->
yeccpars2_43(S, ']', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 47, Ss, Stack, T, Ts, Tzr);
yeccpars2_43(S, '|', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 48, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 48, Ss, Stack, T, Ts, Tzr);
+yeccpars2_43(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_44(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_|Nss] = Ss,
@@ -1076,7 +1114,9 @@ yeccpars2_47(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
%% yeccpars2_48: see yeccpars2_24
yeccpars2_49(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 50, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 50, Ss, Stack, T, Ts, Tzr);
+yeccpars2_49(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_50(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -1091,7 +1131,9 @@ yeccpars2_52(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_tail_literal(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_53(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 23, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 23, Ss, Stack, T, Ts, Tzr);
+yeccpars2_53(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_54(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -1104,7 +1146,9 @@ yeccpars2_55(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_module_attribute(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_56(S, 'end', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 314, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 314, Ss, Stack, T, Ts, Tzr);
+yeccpars2_56(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_57(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_anno_function_name(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
@@ -1121,18 +1165,26 @@ yeccpars2_59(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_313(_S, Cat, [59 | Ss], NewStack, T, Ts, Tzr).
yeccpars2_60(S, '=', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 96, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 96, Ss, Stack, T, Ts, Tzr);
+yeccpars2_60(_, _, _, _, T, _, _) ->
+ yeccerror(T).
%% yeccpars2_61: see yeccpars2_14
yeccpars2_62(S, '-|', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 63, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 63, Ss, Stack, T, Ts, Tzr);
+yeccpars2_62(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_63(S, '[', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 65, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 65, Ss, Stack, T, Ts, Tzr);
+yeccpars2_63(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_64(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 95, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 95, Ss, Stack, T, Ts, Tzr);
+yeccpars2_64(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_65(S, ']', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 73, Ss, Stack, T, Ts, Tzr);
@@ -1147,7 +1199,9 @@ yeccpars2_67(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_atomic_constant(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
yeccpars2_68(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 94, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 94, Ss, Stack, T, Ts, Tzr);
+yeccpars2_68(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_69(S, ',', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 92, Ss, Stack, T, Ts, Tzr);
@@ -1197,7 +1251,9 @@ yeccpars2_79(S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_85(S, Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_80(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 82, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 82, Ss, Stack, T, Ts, Tzr);
+yeccpars2_80(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_81(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_|Nss] = Ss,
@@ -1214,7 +1270,9 @@ yeccpars2_83(S, ',', Ss, Stack, T, Ts, Tzr) ->
yeccpars2_83(S, ']', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 86, Ss, Stack, T, Ts, Tzr);
yeccpars2_83(S, '|', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 87, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 87, Ss, Stack, T, Ts, Tzr);
+yeccpars2_83(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_84(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -1234,7 +1292,9 @@ yeccpars2_85(S, integer, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_85(S, string, Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 78, Ss, Stack, T, Ts, Tzr);
yeccpars2_85(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 79, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 79, Ss, Stack, T, Ts, Tzr);
+yeccpars2_85(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_86(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
NewStack = yeccpars2_86_(Stack),
@@ -1243,7 +1303,9 @@ yeccpars2_86(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
%% yeccpars2_87: see yeccpars2_85
yeccpars2_88(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 89, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 89, Ss, Stack, T, Ts, Tzr);
+yeccpars2_88(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_89(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -1277,7 +1339,9 @@ yeccpars2_95(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_96(S, '(', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 99, Ss, Stack, T, Ts, Tzr);
yeccpars2_96(S, 'fun', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 100, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 100, Ss, Stack, T, Ts, Tzr);
+yeccpars2_96(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_97(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_anno_fun(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
@@ -1288,23 +1352,31 @@ yeccpars2_98(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_function_definition(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_99(S, 'fun', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 100, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 100, Ss, Stack, T, Ts, Tzr);
+yeccpars2_99(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_100(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 101, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 101, Ss, Stack, T, Ts, Tzr);
+yeccpars2_100(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_101(S, '(', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 105, Ss, Stack, T, Ts, Tzr);
yeccpars2_101(S, ')', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 106, Ss, Stack, T, Ts, Tzr);
yeccpars2_101(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr);
+yeccpars2_101(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_102(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_anno_variable(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_103(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 306, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 306, Ss, Stack, T, Ts, Tzr);
+yeccpars2_103(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_104(S, ',', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 304, Ss, Stack, T, Ts, Tzr);
@@ -1313,10 +1385,14 @@ yeccpars2_104(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_anno_variables(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
yeccpars2_105(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr);
+yeccpars2_105(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_106(S, '->', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 108, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 108, Ss, Stack, T, Ts, Tzr);
+yeccpars2_106(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_107(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
NewStack = yeccpars2_107_(Stack),
@@ -1368,7 +1444,9 @@ yeccpars2_cont_108(S, 'receive', Ss, Stack, T, Ts, Tzr) ->
yeccpars2_cont_108(S, 'try', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 143, Ss, Stack, T, Ts, Tzr);
yeccpars2_cont_108(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 144, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 144, Ss, Stack, T, Ts, Tzr);
+yeccpars2_cont_108(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_109(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_single_expression(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
@@ -1433,7 +1511,9 @@ yeccpars2_128(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_fun_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_129(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 287, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 287, Ss, Stack, T, Ts, Tzr);
+yeccpars2_129(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_130(S, char, Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 32, Ss, Stack, T, Ts, Tzr);
@@ -1509,7 +1589,9 @@ yeccpars2_139(S, '(', Ss, Stack, T, Ts, Tzr) ->
yeccpars2_139(S, '<', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 155, Ss, Stack, T, Ts, Tzr);
yeccpars2_139(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr);
+yeccpars2_139(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_140(S, '(', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 61, Ss, Stack, T, Ts, Tzr);
@@ -1562,7 +1644,9 @@ yeccpars2_144(S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_cont_108(S, Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_145(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 150, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 150, Ss, Stack, T, Ts, Tzr);
+yeccpars2_145(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_146(S, ',', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 148, Ss, Stack, T, Ts, Tzr);
@@ -1588,12 +1672,16 @@ yeccpars2_150(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_tuple(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_151(S, 'of', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 152, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 152, Ss, Stack, T, Ts, Tzr);
+yeccpars2_151(_, _, _, _, T, _, _) ->
+ yeccerror(T).
%% yeccpars2_152: see yeccpars2_139
yeccpars2_153(S, '->', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 159, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 159, Ss, Stack, T, Ts, Tzr);
+yeccpars2_153(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_154(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
NewStack = yeccpars2_154_(Stack),
@@ -1604,10 +1692,14 @@ yeccpars2_155(S, '(', Ss, Stack, T, Ts, Tzr) ->
yeccpars2_155(S, '>', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 157, Ss, Stack, T, Ts, Tzr);
yeccpars2_155(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr);
+yeccpars2_155(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_156(S, '>', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 158, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 158, Ss, Stack, T, Ts, Tzr);
+yeccpars2_156(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_157(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_|Nss] = Ss,
@@ -1622,12 +1714,16 @@ yeccpars2_158(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
%% yeccpars2_159: see yeccpars2_108
yeccpars2_160(S, 'catch', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 161, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 161, Ss, Stack, T, Ts, Tzr);
+yeccpars2_160(_, _, _, _, T, _, _) ->
+ yeccerror(T).
%% yeccpars2_161: see yeccpars2_139
yeccpars2_162(S, '->', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 163, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 163, Ss, Stack, T, Ts, Tzr);
+yeccpars2_162(_, _, _, _, T, _, _) ->
+ yeccerror(T).
%% yeccpars2_163: see yeccpars2_108
@@ -1651,7 +1747,9 @@ yeccpars2_168(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_other_pattern(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_169(S, 'when', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 240, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 240, Ss, Stack, T, Ts, Tzr);
+yeccpars2_169(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_170(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_anno_clause(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
@@ -1675,7 +1773,9 @@ yeccpars2_175(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_clause_pattern(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
yeccpars2_176(S, 'after', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 182, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 182, Ss, Stack, T, Ts, Tzr);
+yeccpars2_176(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_177(S, '#', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 178, Ss, Stack, T, Ts, Tzr);
@@ -1704,7 +1804,9 @@ yeccpars2_177(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_anno_clauses(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
yeccpars2_178(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 222, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 222, Ss, Stack, T, Ts, Tzr);
+yeccpars2_178(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_179(S, '#', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 178, Ss, Stack, T, Ts, Tzr);
@@ -1777,7 +1879,9 @@ yeccpars2_183(S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_cont_24(S, Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_184(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 201, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 201, Ss, Stack, T, Ts, Tzr);
+yeccpars2_184(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_185(S, ',', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 199, Ss, Stack, T, Ts, Tzr);
@@ -1811,10 +1915,14 @@ yeccpars2_188(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_anno_variable(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_189(S, '-|', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 193, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 193, Ss, Stack, T, Ts, Tzr);
+yeccpars2_189(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_190(S, '=', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 191, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 191, Ss, Stack, T, Ts, Tzr);
+yeccpars2_190(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_191(S, '#', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 178, Ss, Stack, T, Ts, Tzr);
@@ -1839,7 +1947,9 @@ yeccpars2_192(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
%% yeccpars2_193: see yeccpars2_63
yeccpars2_194(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 195, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 195, Ss, Stack, T, Ts, Tzr);
+yeccpars2_194(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_195(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_,_|Nss] = Ss,
@@ -1849,7 +1959,9 @@ yeccpars2_195(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
%% yeccpars2_196: see yeccpars2_63
yeccpars2_197(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 198, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 198, Ss, Stack, T, Ts, Tzr);
+yeccpars2_197(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_198(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_,_|Nss] = Ss,
@@ -1869,7 +1981,9 @@ yeccpars2_201(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_tuple_pattern(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_202(S, '->', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 203, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 203, Ss, Stack, T, Ts, Tzr);
+yeccpars2_202(_, _, _, _, T, _, _) ->
+ yeccerror(T).
%% yeccpars2_203: see yeccpars2_108
@@ -1883,7 +1997,9 @@ yeccpars2_205(S, ',', Ss, Stack, T, Ts, Tzr) ->
yeccpars2_205(S, ']', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 208, Ss, Stack, T, Ts, Tzr);
yeccpars2_205(S, '|', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 209, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 209, Ss, Stack, T, Ts, Tzr);
+yeccpars2_205(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_206(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -1899,7 +2015,9 @@ yeccpars2_208(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
%% yeccpars2_209: see yeccpars2_191
yeccpars2_210(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 211, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 211, Ss, Stack, T, Ts, Tzr);
+yeccpars2_210(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_211(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -1914,7 +2032,9 @@ yeccpars2_213(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_tail_pattern(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_214(S, '>', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 216, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 216, Ss, Stack, T, Ts, Tzr);
+yeccpars2_214(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_215(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_|Nss] = Ss,
@@ -1932,12 +2052,16 @@ yeccpars2_217(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_anno_pattern(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_218(S, '-|', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 219, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 219, Ss, Stack, T, Ts, Tzr);
+yeccpars2_218(_, _, _, _, T, _, _) ->
+ yeccerror(T).
%% yeccpars2_219: see yeccpars2_63
yeccpars2_220(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 221, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 221, Ss, Stack, T, Ts, Tzr);
+yeccpars2_220(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_221(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_,_|Nss] = Ss,
@@ -1947,10 +2071,14 @@ yeccpars2_221(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_222(S, '#', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 225, Ss, Stack, T, Ts, Tzr);
yeccpars2_222(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 226, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 226, Ss, Stack, T, Ts, Tzr);
+yeccpars2_222(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_223(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 236, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 236, Ss, Stack, T, Ts, Tzr);
+yeccpars2_223(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_224(S, ',', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 234, Ss, Stack, T, Ts, Tzr);
@@ -1959,10 +2087,14 @@ yeccpars2_224(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_segment_patterns(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
yeccpars2_225(S, '<', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 228, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 228, Ss, Stack, T, Ts, Tzr);
+yeccpars2_225(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_226(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 227, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 227, Ss, Stack, T, Ts, Tzr);
+yeccpars2_226(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_227(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_|Nss] = Ss,
@@ -1972,15 +2104,21 @@ yeccpars2_227(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
%% yeccpars2_228: see yeccpars2_191
yeccpars2_229(S, '>', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 230, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 230, Ss, Stack, T, Ts, Tzr);
+yeccpars2_229(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_230(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 231, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 231, Ss, Stack, T, Ts, Tzr);
+yeccpars2_230(_, _, _, _, T, _, _) ->
+ yeccerror(T).
%% yeccpars2_231: see yeccpars2_191
yeccpars2_232(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 233, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 233, Ss, Stack, T, Ts, Tzr);
+yeccpars2_232(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_233(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_,_,_,_|Nss] = Ss,
@@ -1988,7 +2126,9 @@ yeccpars2_233(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_segment_pattern(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_234(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 225, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 225, Ss, Stack, T, Ts, Tzr);
+yeccpars2_234(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_235(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -1996,7 +2136,9 @@ yeccpars2_235(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_segment_patterns(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_236(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 237, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 237, Ss, Stack, T, Ts, Tzr);
+yeccpars2_236(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_237(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_,_|Nss] = Ss,
@@ -2016,7 +2158,9 @@ yeccpars2_239(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
%% yeccpars2_240: see yeccpars2_108
yeccpars2_241(S, '->', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 242, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 242, Ss, Stack, T, Ts, Tzr);
+yeccpars2_241(_, _, _, _, T, _, _) ->
+ yeccerror(T).
%% yeccpars2_242: see yeccpars2_108
@@ -2026,7 +2170,9 @@ yeccpars2_243(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_clause(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_244(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 246, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 246, Ss, Stack, T, Ts, Tzr);
+yeccpars2_244(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_245(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -2053,7 +2199,9 @@ yeccpars2_246(S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_cont_108(S, Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_247(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 249, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 249, Ss, Stack, T, Ts, Tzr);
+yeccpars2_247(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_248(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_|Nss] = Ss,
@@ -2066,7 +2214,9 @@ yeccpars2_249(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_arg_list(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_250(S, in, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 251, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 251, Ss, Stack, T, Ts, Tzr);
+yeccpars2_250(_, _, _, _, T, _, _) ->
+ yeccerror(T).
%% yeccpars2_251: see yeccpars2_108
@@ -2076,12 +2226,16 @@ yeccpars2_252(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_letrec_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_253(S, '=', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 254, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 254, Ss, Stack, T, Ts, Tzr);
+yeccpars2_253(_, _, _, _, T, _, _) ->
+ yeccerror(T).
%% yeccpars2_254: see yeccpars2_108
yeccpars2_255(S, in, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 256, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 256, Ss, Stack, T, Ts, Tzr);
+yeccpars2_255(_, _, _, _, T, _, _) ->
+ yeccerror(T).
%% yeccpars2_256: see yeccpars2_108
@@ -2103,7 +2257,9 @@ yeccpars2_260(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_catch_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_261(S, 'of', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 262, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 262, Ss, Stack, T, Ts, Tzr);
+yeccpars2_261(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_262(S, '#', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 178, Ss, Stack, T, Ts, Tzr);
@@ -2123,7 +2279,9 @@ yeccpars2_262(S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_cont_24(S, Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_263(S, 'end', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 264, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 264, Ss, Stack, T, Ts, Tzr);
+yeccpars2_263(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_264(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_,_|Nss] = Ss,
@@ -2131,7 +2289,9 @@ yeccpars2_264(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_case_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_265(S, ':', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 266, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 266, Ss, Stack, T, Ts, Tzr);
+yeccpars2_265(_, _, _, _, T, _, _) ->
+ yeccerror(T).
%% yeccpars2_266: see yeccpars2_108
@@ -2154,7 +2314,9 @@ yeccpars2_271(S, ',', Ss, Stack, T, Ts, Tzr) ->
yeccpars2_271(S, ']', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 274, Ss, Stack, T, Ts, Tzr);
yeccpars2_271(S, '|', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 275, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 275, Ss, Stack, T, Ts, Tzr);
+yeccpars2_271(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_272(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -2170,7 +2332,9 @@ yeccpars2_274(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
%% yeccpars2_275: see yeccpars2_108
yeccpars2_276(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 277, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 277, Ss, Stack, T, Ts, Tzr);
+yeccpars2_276(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_277(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -2185,7 +2349,9 @@ yeccpars2_279(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_tail(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_280(S, '>', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 282, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 282, Ss, Stack, T, Ts, Tzr);
+yeccpars2_280(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_281(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_|Nss] = Ss,
@@ -2198,12 +2364,16 @@ yeccpars2_282(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_expression(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_283(S, '-|', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 284, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 284, Ss, Stack, T, Ts, Tzr);
+yeccpars2_283(_, _, _, _, T, _, _) ->
+ yeccerror(T).
%% yeccpars2_284: see yeccpars2_63
yeccpars2_285(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 286, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 286, Ss, Stack, T, Ts, Tzr);
+yeccpars2_285(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_286(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_,_|Nss] = Ss,
@@ -2213,10 +2383,14 @@ yeccpars2_286(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_287(S, '#', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 290, Ss, Stack, T, Ts, Tzr);
yeccpars2_287(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 291, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 291, Ss, Stack, T, Ts, Tzr);
+yeccpars2_287(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_288(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 301, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 301, Ss, Stack, T, Ts, Tzr);
+yeccpars2_288(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_289(S, ',', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 299, Ss, Stack, T, Ts, Tzr);
@@ -2225,10 +2399,14 @@ yeccpars2_289(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_segments(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
yeccpars2_290(S, '<', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 293, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 293, Ss, Stack, T, Ts, Tzr);
+yeccpars2_290(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_291(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 292, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 292, Ss, Stack, T, Ts, Tzr);
+yeccpars2_291(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_292(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_|Nss] = Ss,
@@ -2238,15 +2416,21 @@ yeccpars2_292(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
%% yeccpars2_293: see yeccpars2_108
yeccpars2_294(S, '>', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 295, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 295, Ss, Stack, T, Ts, Tzr);
+yeccpars2_294(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_295(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 296, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 296, Ss, Stack, T, Ts, Tzr);
+yeccpars2_295(_, _, _, _, T, _, _) ->
+ yeccerror(T).
%% yeccpars2_296: see yeccpars2_108
yeccpars2_297(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 298, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 298, Ss, Stack, T, Ts, Tzr);
+yeccpars2_297(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_298(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_,_,_,_|Nss] = Ss,
@@ -2254,7 +2438,9 @@ yeccpars2_298(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_segment(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_299(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 290, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 290, Ss, Stack, T, Ts, Tzr);
+yeccpars2_299(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_300(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -2262,7 +2448,9 @@ yeccpars2_300(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_segments(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_301(S, '#', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 302, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 302, Ss, Stack, T, Ts, Tzr);
+yeccpars2_301(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_302(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_,_|Nss] = Ss,
@@ -2270,12 +2458,16 @@ yeccpars2_302(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_binary(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_303(S, '-|', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 196, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 196, Ss, Stack, T, Ts, Tzr);
+yeccpars2_303(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_304(S, '(', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 105, Ss, Stack, T, Ts, Tzr);
yeccpars2_304(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr);
+yeccpars2_304(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_305(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -2283,7 +2475,9 @@ yeccpars2_305(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_anno_variables(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_306(S, '->', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 307, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 307, Ss, Stack, T, Ts, Tzr);
+yeccpars2_306(_, _, _, _, T, _, _) ->
+ yeccerror(T).
%% yeccpars2_307: see yeccpars2_108
@@ -2293,12 +2487,16 @@ yeccpars2_308(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_fun_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_309(S, '-|', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 310, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 310, Ss, Stack, T, Ts, Tzr);
+yeccpars2_309(_, _, _, _, T, _, _) ->
+ yeccerror(T).
%% yeccpars2_310: see yeccpars2_63
yeccpars2_311(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 312, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 312, Ss, Stack, T, Ts, Tzr);
+yeccpars2_311(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_312(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_,_|Nss] = Ss,
@@ -2316,7 +2514,9 @@ yeccpars2_314(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_module_definition(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_315(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 316, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 316, Ss, Stack, T, Ts, Tzr);
+yeccpars2_315(_, _, _, _, T, _, _) ->
+ yeccerror(T).
%% yeccpars2_316: see yeccpars2_4
@@ -2331,15 +2531,21 @@ yeccpars2_318(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_58(_S, Cat, [318 | Ss], NewStack, T, Ts, Tzr).
yeccpars2_319(S, 'end', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 320, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 320, Ss, Stack, T, Ts, Tzr);
+yeccpars2_319(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_320(S, '-|', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 321, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 321, Ss, Stack, T, Ts, Tzr);
+yeccpars2_320(_, _, _, _, T, _, _) ->
+ yeccerror(T).
%% yeccpars2_321: see yeccpars2_63
yeccpars2_322(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 323, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 323, Ss, Stack, T, Ts, Tzr);
+yeccpars2_322(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_323(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_,_,_,_,_,_,_|Nss] = Ss,
diff --git a/bootstrap/lib/kernel/ebin/dist_util.beam b/bootstrap/lib/kernel/ebin/dist_util.beam
index 167a70e99d..93f0a3754a 100644
--- a/bootstrap/lib/kernel/ebin/dist_util.beam
+++ b/bootstrap/lib/kernel/ebin/dist_util.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/erl_epmd.beam b/bootstrap/lib/kernel/ebin/erl_epmd.beam
index 68ef714e17..847ed69e23 100644
--- a/bootstrap/lib/kernel/ebin/erl_epmd.beam
+++ b/bootstrap/lib/kernel/ebin/erl_epmd.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/gen_sctp.beam b/bootstrap/lib/kernel/ebin/gen_sctp.beam
index a55e9090a5..1d51915a4f 100644
--- a/bootstrap/lib/kernel/ebin/gen_sctp.beam
+++ b/bootstrap/lib/kernel/ebin/gen_sctp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/gen_tcp.beam b/bootstrap/lib/kernel/ebin/gen_tcp.beam
index fa87a6726b..f684fe1bf2 100644
--- a/bootstrap/lib/kernel/ebin/gen_tcp.beam
+++ b/bootstrap/lib/kernel/ebin/gen_tcp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/gen_udp.beam b/bootstrap/lib/kernel/ebin/gen_udp.beam
index 5af947d638..1591c85048 100644
--- a/bootstrap/lib/kernel/ebin/gen_udp.beam
+++ b/bootstrap/lib/kernel/ebin/gen_udp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam b/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam
index 70e35c2076..0c39512bb3 100644
--- a/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam
+++ b/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet6_sctp.beam b/bootstrap/lib/kernel/ebin/inet6_sctp.beam
index 0e71998ed9..d9917f0347 100644
--- a/bootstrap/lib/kernel/ebin/inet6_sctp.beam
+++ b/bootstrap/lib/kernel/ebin/inet6_sctp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_config.beam b/bootstrap/lib/kernel/ebin/inet_config.beam
index edc1e2f6fb..b3061fffa1 100644
--- a/bootstrap/lib/kernel/ebin/inet_config.beam
+++ b/bootstrap/lib/kernel/ebin/inet_config.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_parse.beam b/bootstrap/lib/kernel/ebin/inet_parse.beam
index 914397158a..5afff695e5 100644
--- a/bootstrap/lib/kernel/ebin/inet_parse.beam
+++ b/bootstrap/lib/kernel/ebin/inet_parse.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_sctp.beam b/bootstrap/lib/kernel/ebin/inet_sctp.beam
index a4d234911d..bfd6b4b252 100644
--- a/bootstrap/lib/kernel/ebin/inet_sctp.beam
+++ b/bootstrap/lib/kernel/ebin/inet_sctp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/kernel.app b/bootstrap/lib/kernel/ebin/kernel.app
index 2b2c82d89c..5ea0891375 100644
--- a/bootstrap/lib/kernel/ebin/kernel.app
+++ b/bootstrap/lib/kernel/ebin/kernel.app
@@ -21,7 +21,7 @@
{application, kernel,
[
{description, "ERTS CXC 138 10"},
- {vsn, "2.14.1"},
+ {vsn, "2.14.2"},
{modules, [application,
application_controller,
application_master,
diff --git a/bootstrap/lib/kernel/ebin/net_kernel.beam b/bootstrap/lib/kernel/ebin/net_kernel.beam
index 4343fc47aa..1245322a7d 100644
--- a/bootstrap/lib/kernel/ebin/net_kernel.beam
+++ b/bootstrap/lib/kernel/ebin/net_kernel.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/beam_lib.beam b/bootstrap/lib/stdlib/ebin/beam_lib.beam
index 5d4a22d334..04681ac12d 100644
--- a/bootstrap/lib/stdlib/ebin/beam_lib.beam
+++ b/bootstrap/lib/stdlib/ebin/beam_lib.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/c.beam b/bootstrap/lib/stdlib/ebin/c.beam
index 099bb5ad90..2202b9105d 100644
--- a/bootstrap/lib/stdlib/ebin/c.beam
+++ b/bootstrap/lib/stdlib/ebin/c.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/digraph.beam b/bootstrap/lib/stdlib/ebin/digraph.beam
index fa37407d53..c68611ccdc 100644
--- a/bootstrap/lib/stdlib/ebin/digraph.beam
+++ b/bootstrap/lib/stdlib/ebin/digraph.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_internal.beam b/bootstrap/lib/stdlib/ebin/erl_internal.beam
index 588f761199..8d080bdacc 100644
--- a/bootstrap/lib/stdlib/ebin/erl_internal.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_internal.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_parse.beam b/bootstrap/lib/stdlib/ebin/erl_parse.beam
index 426bd23e36..4d07a75daf 100644
--- a/bootstrap/lib/stdlib/ebin/erl_parse.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_parse.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/file_sorter.beam b/bootstrap/lib/stdlib/ebin/file_sorter.beam
index 90627df431..29eb281856 100644
--- a/bootstrap/lib/stdlib/ebin/file_sorter.beam
+++ b/bootstrap/lib/stdlib/ebin/file_sorter.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/ms_transform.beam b/bootstrap/lib/stdlib/ebin/ms_transform.beam
index 2a0745f786..42335a6a00 100644
--- a/bootstrap/lib/stdlib/ebin/ms_transform.beam
+++ b/bootstrap/lib/stdlib/ebin/ms_transform.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/otp_internal.beam b/bootstrap/lib/stdlib/ebin/otp_internal.beam
index 9a031e8eac..709d1379dd 100644
--- a/bootstrap/lib/stdlib/ebin/otp_internal.beam
+++ b/bootstrap/lib/stdlib/ebin/otp_internal.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/qlc.beam b/bootstrap/lib/stdlib/ebin/qlc.beam
index 2e05a4c546..da0adc0c23 100644
--- a/bootstrap/lib/stdlib/ebin/qlc.beam
+++ b/bootstrap/lib/stdlib/ebin/qlc.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/stdlib.app b/bootstrap/lib/stdlib/ebin/stdlib.app
index 6ab708e43c..6aac1e2f19 100644
--- a/bootstrap/lib/stdlib/ebin/stdlib.app
+++ b/bootstrap/lib/stdlib/ebin/stdlib.app
@@ -19,7 +19,7 @@
%%
{application, stdlib,
[{description, "ERTS CXC 138 10"},
- {vsn, "1.17.1"},
+ {vsn, "1.17.2"},
{modules, [array,
base64,
beam_lib,
diff --git a/bootstrap/lib/stdlib/ebin/supervisor.beam b/bootstrap/lib/stdlib/ebin/supervisor.beam
index 54811dad66..a9e30b4d5d 100644
--- a/bootstrap/lib/stdlib/ebin/supervisor.beam
+++ b/bootstrap/lib/stdlib/ebin/supervisor.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/timer.beam b/bootstrap/lib/stdlib/ebin/timer.beam
index 1020f78632..1f84ff37ac 100644
--- a/bootstrap/lib/stdlib/ebin/timer.beam
+++ b/bootstrap/lib/stdlib/ebin/timer.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/egen/erl_parse.erl b/bootstrap/lib/stdlib/egen/erl_parse.erl
index fd245f386a..cd5102a680 100644
--- a/bootstrap/lib/stdlib/egen/erl_parse.erl
+++ b/bootstrap/lib/stdlib/egen/erl_parse.erl
@@ -556,7 +556,7 @@ get_attribute(L, Name) ->
get_attributes(L) ->
erl_scan:attributes_info(L).
--file("/usr/local/otp_product/releases/sles10_32_R14A_patched/lib/parsetools-2.0.3/include/yeccpre.hrl", 0).
+-file("/usr/local/otp/releases/sles10_32_R14B_patched/lib/parsetools-2.0.4/include/yeccpre.hrl", 0).
%%
%% %CopyrightBegin%
%%
@@ -585,8 +585,8 @@ get_attributes(L) ->
parse(Tokens) ->
yeccpars0(Tokens, {no_func, no_line}, 0, [], []).
--spec parse_and_scan({function() | {atom(), atom()}, [_]} | {atom(), atom(), [_]}) ->
- yecc_ret().
+-spec parse_and_scan({function() | {atom(), atom()}, [_]}
+ | {atom(), atom(), [_]}) -> yecc_ret().
parse_and_scan({F, A}) -> % Fun or {M, F}
yeccpars0([], {{F, A}, no_line}, 0, [], []);
parse_and_scan({M, F, A}) ->
@@ -603,7 +603,7 @@ format_error(Message) ->
%% To be used in grammar files to throw an error message to the parser
%% toplevel. Doesn't have to be exported!
--compile({nowarn_unused_function,{return_error,2}}).
+-compile({nowarn_unused_function, return_error/2}).
-spec return_error(integer(), any()) -> no_return().
return_error(Line, Message) ->
throw({error, {Line, ?MODULE, Message}}).
@@ -616,10 +616,7 @@ yeccpars0(Tokens, Tzr, State, States, Vstack) ->
error: Error ->
Stacktrace = erlang:get_stacktrace(),
try yecc_error_type(Error, Stacktrace) of
- {syntax_error, Token} ->
- yeccerror(Token);
- {missing_in_goto_table=Tag, Symbol, State} ->
- Desc = {Symbol, State, Tag},
+ Desc ->
erlang:raise(error, {yecc_bug, ?CODE_VERSION, Desc},
Stacktrace)
catch _:_ -> erlang:raise(error, Error, Stacktrace)
@@ -629,13 +626,15 @@ yeccpars0(Tokens, Tzr, State, States, Vstack) ->
Error
end.
-yecc_error_type(function_clause, [{?MODULE,F,[State,_,_,_,Token,_,_]} | _]) ->
+yecc_error_type(function_clause, [{?MODULE,F,ArityOrArgs} | _]) ->
case atom_to_list(F) of
- "yeccpars2" ++ _ ->
- {syntax_error, Token};
"yeccgoto_" ++ SymbolL ->
{ok,[{atom,_,Symbol}],_} = erl_scan:string(SymbolL),
- {missing_in_goto_table, Symbol, State}
+ State = case ArityOrArgs of
+ [S,_,_,_,_,_,_] -> S;
+ _ -> state_is_unknown
+ end,
+ {Symbol, State, missing_in_goto_table}
end.
yeccpars1([Token | Tokens], Tzr, State, States, Vstack) ->
@@ -700,11 +699,13 @@ yecctoken_end_location(Token) ->
yecctoken_location(Token)
end.
+-compile({nowarn_unused_function, yeccerror/1}).
yeccerror(Token) ->
Text = yecctoken_to_string(Token),
Location = yecctoken_location(Token),
{error, {Location, ?MODULE, ["syntax error before: ", Text]}}.
+-compile({nowarn_unused_function, yecctoken_to_string/1}).
yecctoken_to_string(Token) ->
case catch erl_scan:token_info(Token, text) of
{text, Txt} -> Txt;
@@ -717,6 +718,7 @@ yecctoken_location(Token) ->
_ -> element(2, Token)
end.
+-compile({nowarn_unused_function, yecctoken2string/1}).
yecctoken2string({atom, _, A}) -> io_lib:write(A);
yecctoken2string({integer,_,N}) -> io_lib:write(N);
yecctoken2string({float,_,F}) -> io_lib:write(F);
@@ -737,7 +739,7 @@ yecctoken2string(Other) ->
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 740).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 742).
yeccpars2(0=S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_0(S, Cat, Ss, Stack, T, Ts, Tzr);
@@ -1670,12 +1672,14 @@ yeccpars2(462=S, Cat, Ss, Stack, T, Ts, Tzr) ->
%% yeccpars2(464=S, Cat, Ss, Stack, T, Ts, Tzr) ->
%% yeccpars2_464(S, Cat, Ss, Stack, T, Ts, Tzr);
yeccpars2(Other, _, _, _, _, _, _) ->
- erlang:error({yecc_bug,"1.3",{missing_state_in_action_table, Other}}).
+ erlang:error({yecc_bug,"1.4",{missing_state_in_action_table, Other}}).
yeccpars2_0(S, '-', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 9, Ss, Stack, T, Ts, Tzr);
yeccpars2_0(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 10, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 10, Ss, Stack, T, Ts, Tzr);
+yeccpars2_0(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_1(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
NewStack = yeccpars2_1_(Stack),
@@ -1688,7 +1692,9 @@ yeccpars2_2(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_rule_clauses(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
yeccpars2_3(S, dot, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 459, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 459, Ss, Stack, T, Ts, Tzr);
+yeccpars2_3(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_4(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
NewStack = yeccpars2_4_(Stack),
@@ -1701,21 +1707,31 @@ yeccpars2_5(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_function_clauses(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
yeccpars2_6(S, dot, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 453, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 453, Ss, Stack, T, Ts, Tzr);
+yeccpars2_6(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_7(_S, '$end', _Ss, Stack, _T, _Ts, _Tzr) ->
- {ok, hd(Stack)}.
+ {ok, hd(Stack)};
+yeccpars2_7(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_8(S, dot, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 452, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 452, Ss, Stack, T, Ts, Tzr);
+yeccpars2_8(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_9(S, atom, Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 292, Ss, Stack, T, Ts, Tzr);
yeccpars2_9(S, spec, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 293, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 293, Ss, Stack, T, Ts, Tzr);
+yeccpars2_9(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_10(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 13, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 13, Ss, Stack, T, Ts, Tzr);
+yeccpars2_10(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_11(S, 'when', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 84, Ss, Stack, T, Ts, Tzr);
@@ -1779,7 +1795,9 @@ yeccpars2_cont_13(S, 'receive', Ss, Stack, T, Ts, Tzr) ->
yeccpars2_cont_13(S, string, Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 65, Ss, Stack, T, Ts, Tzr);
yeccpars2_cont_13(S, 'try', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 66, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 66, Ss, Stack, T, Ts, Tzr);
+yeccpars2_cont_13(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_expr_max(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
@@ -1832,7 +1850,9 @@ yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_expr_max(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_26(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 280, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 280, Ss, Stack, T, Ts, Tzr);
+yeccpars2_26(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_27(S, '#', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 275, Ss, Stack, T, Ts, Tzr);
@@ -1953,7 +1973,9 @@ yeccpars2_43(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_expr_max(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_44(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 211, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 211, Ss, Stack, T, Ts, Tzr);
+yeccpars2_44(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_45(S, '#', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 44, Ss, Stack, T, Ts, Tzr);
@@ -1992,7 +2014,9 @@ yeccpars2_48(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_prefix_op(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_49(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 208, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 208, Ss, Stack, T, Ts, Tzr);
+yeccpars2_49(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_50(S, '(', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 45, Ss, Stack, T, Ts, Tzr);
@@ -2063,7 +2087,9 @@ yeccpars2_58(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_59(S, '(', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 13, Ss, Stack, T, Ts, Tzr);
yeccpars2_59(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 152, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 152, Ss, Stack, T, Ts, Tzr);
+yeccpars2_59(_, _, _, _, T, _, _) ->
+ yeccerror(T).
%% yeccpars2_60: see yeccpars2_45
@@ -2074,7 +2100,9 @@ yeccpars2_62(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_prefix_op(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_63(S, '[', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 127, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 127, Ss, Stack, T, Ts, Tzr);
+yeccpars2_63(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_64(S, '#', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 44, Ss, Stack, T, Ts, Tzr);
@@ -2141,7 +2169,9 @@ yeccpars2_68(S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_cont_13(S, Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_69(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 71, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 71, Ss, Stack, T, Ts, Tzr);
+yeccpars2_69(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_70(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_|Nss] = Ss,
@@ -2201,7 +2231,9 @@ yeccpars2_77(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_78(S, 'after', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 74, Ss, Stack, T, Ts, Tzr);
yeccpars2_78(S, 'catch', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 75, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 75, Ss, Stack, T, Ts, Tzr);
+yeccpars2_78(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_79(S, ';', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 80, Ss, Stack, T, Ts, Tzr);
@@ -2222,7 +2254,9 @@ yeccpars2_82(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_try_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_83(S, '->', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 90, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 90, Ss, Stack, T, Ts, Tzr);
+yeccpars2_83(_, _, _, _, T, _, _) ->
+ yeccerror(T).
%% yeccpars2_84: see yeccpars2_45
@@ -2259,7 +2293,9 @@ yeccpars2_91(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_92(S, 'after', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 109, Ss, Stack, T, Ts, Tzr);
yeccpars2_92(S, 'end', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 110, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 110, Ss, Stack, T, Ts, Tzr);
+yeccpars2_92(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_93(S, ';', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 107, Ss, Stack, T, Ts, Tzr);
@@ -2335,7 +2371,9 @@ yeccpars2_110(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_try_catch(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_111(S, 'end', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 112, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 112, Ss, Stack, T, Ts, Tzr);
+yeccpars2_111(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_,_|Nss] = Ss,
@@ -2343,7 +2381,9 @@ yeccpars2_112(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_try_catch(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_113(S, 'end', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 114, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 114, Ss, Stack, T, Ts, Tzr);
+yeccpars2_113(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_114(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -2358,14 +2398,18 @@ yeccpars2_115(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_116(S, 'after', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 121, Ss, Stack, T, Ts, Tzr);
yeccpars2_116(S, 'end', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 122, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 122, Ss, Stack, T, Ts, Tzr);
+yeccpars2_116(_, _, _, _, T, _, _) ->
+ yeccerror(T).
%% yeccpars2_117: see yeccpars2_45
%% yeccpars2_118: see yeccpars2_83
yeccpars2_119(S, 'end', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 120, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 120, Ss, Stack, T, Ts, Tzr);
+yeccpars2_119(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_120(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_,_|Nss] = Ss,
@@ -2382,7 +2426,9 @@ yeccpars2_122(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
%% yeccpars2_123: see yeccpars2_83
yeccpars2_124(S, 'end', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 125, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 125, Ss, Stack, T, Ts, Tzr);
+yeccpars2_124(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_,_,_|Nss] = Ss,
@@ -2390,17 +2436,23 @@ yeccpars2_125(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_receive_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_126(S, 'end', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 141, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 141, Ss, Stack, T, Ts, Tzr);
+yeccpars2_126(_, _, _, _, T, _, _) ->
+ yeccerror(T).
%% yeccpars2_127: see yeccpars2_45
yeccpars2_128(S, '||', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 129, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 129, Ss, Stack, T, Ts, Tzr);
+yeccpars2_128(_, _, _, _, T, _, _) ->
+ yeccerror(T).
%% yeccpars2_129: see yeccpars2_45
yeccpars2_130(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 140, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 140, Ss, Stack, T, Ts, Tzr);
+yeccpars2_130(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_131(S, ',', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 138, Ss, Stack, T, Ts, Tzr);
@@ -2450,7 +2502,9 @@ yeccpars2_141(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_query_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_142(S, 'end', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 148, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 148, Ss, Stack, T, Ts, Tzr);
+yeccpars2_142(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_143(S, ';', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 146, Ss, Stack, T, Ts, Tzr);
@@ -2478,7 +2532,9 @@ yeccpars2_148(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_if_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_149(S, 'end', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 163, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 163, Ss, Stack, T, Ts, Tzr);
+yeccpars2_149(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_150(S, ';', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 161, Ss, Stack, T, Ts, Tzr);
@@ -2495,19 +2551,29 @@ yeccpars2_151(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_152(S, '/', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 153, Ss, Stack, T, Ts, Tzr);
yeccpars2_152(S, ':', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 154, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 154, Ss, Stack, T, Ts, Tzr);
+yeccpars2_152(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_153(S, integer, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 158, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 158, Ss, Stack, T, Ts, Tzr);
+yeccpars2_153(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_154(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 155, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 155, Ss, Stack, T, Ts, Tzr);
+yeccpars2_154(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_155(S, '/', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 156, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 156, Ss, Stack, T, Ts, Tzr);
+yeccpars2_155(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_156(S, integer, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 157, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 157, Ss, Stack, T, Ts, Tzr);
+yeccpars2_156(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_157(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_,_,_|Nss] = Ss,
@@ -2544,12 +2610,16 @@ yeccpars2_164(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_165(S, 'of', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 166, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 166, Ss, Stack, T, Ts, Tzr);
+yeccpars2_165(_, _, _, _, T, _, _) ->
+ yeccerror(T).
%% yeccpars2_166: see yeccpars2_45
yeccpars2_167(S, 'end', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 168, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 168, Ss, Stack, T, Ts, Tzr);
+yeccpars2_167(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_168(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_,_|Nss] = Ss,
@@ -2557,7 +2627,9 @@ yeccpars2_168(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_case_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_169(S, 'end', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 170, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 170, Ss, Stack, T, Ts, Tzr);
+yeccpars2_169(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_170(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -2588,7 +2660,9 @@ yeccpars2_175(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
%% yeccpars2_176: see yeccpars2_45
yeccpars2_177(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 178, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 178, Ss, Stack, T, Ts, Tzr);
+yeccpars2_177(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_178(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -2600,7 +2674,9 @@ yeccpars2_179(S, ',', Ss, Stack, T, Ts, Tzr) ->
yeccpars2_179(S, ']', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 175, Ss, Stack, T, Ts, Tzr);
yeccpars2_179(S, '|', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 176, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 176, Ss, Stack, T, Ts, Tzr);
+yeccpars2_179(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_180(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -2633,7 +2709,9 @@ yeccpars2_184(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_expr_max(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_185(S, '>>', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 190, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 190, Ss, Stack, T, Ts, Tzr);
+yeccpars2_185(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_186(S, ',', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 188, Ss, Stack, T, Ts, Tzr);
@@ -2678,7 +2756,9 @@ yeccpars2_190(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
%% yeccpars2_191: see yeccpars2_45
yeccpars2_192(S, '>>', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 193, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 193, Ss, Stack, T, Ts, Tzr);
+yeccpars2_192(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_193(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_,_|Nss] = Ss,
@@ -2707,7 +2787,9 @@ yeccpars2_198(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_bin_element(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_199(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 202, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 202, Ss, Stack, T, Ts, Tzr);
+yeccpars2_199(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_200(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_|Nss] = Ss,
@@ -2727,7 +2809,9 @@ yeccpars2_202(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_bit_type(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
yeccpars2_203(S, integer, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 204, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 204, Ss, Stack, T, Ts, Tzr);
+yeccpars2_203(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_204(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -2752,7 +2836,9 @@ yeccpars2_208(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_expr_900(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_209(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 210, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 210, Ss, Stack, T, Ts, Tzr);
+yeccpars2_209(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_210(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -2762,7 +2848,9 @@ yeccpars2_210(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_211(S, '.', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 213, Ss, Stack, T, Ts, Tzr);
yeccpars2_211(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 214, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 214, Ss, Stack, T, Ts, Tzr);
+yeccpars2_211(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_212(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -2770,7 +2858,9 @@ yeccpars2_212(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_record_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_213(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 227, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 227, Ss, Stack, T, Ts, Tzr);
+yeccpars2_213(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_214(S, '}', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 219, Ss, Stack, T, Ts, Tzr);
@@ -2778,7 +2868,9 @@ yeccpars2_214(S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_224(S, Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_215(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 226, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 226, Ss, Stack, T, Ts, Tzr);
+yeccpars2_215(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_216(S, ',', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 224, Ss, Stack, T, Ts, Tzr);
@@ -2787,10 +2879,14 @@ yeccpars2_216(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_record_fields(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
yeccpars2_217(S, '=', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 222, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 222, Ss, Stack, T, Ts, Tzr);
+yeccpars2_217(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_218(S, '=', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 220, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 220, Ss, Stack, T, Ts, Tzr);
+yeccpars2_218(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_219(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_|Nss] = Ss,
@@ -2814,7 +2910,9 @@ yeccpars2_223(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_224(S, atom, Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 217, Ss, Stack, T, Ts, Tzr);
yeccpars2_224(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 218, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 218, Ss, Stack, T, Ts, Tzr);
+yeccpars2_224(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_225(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -3005,7 +3103,9 @@ yeccpars2_270(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_function_call(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_271(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 274, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 274, Ss, Stack, T, Ts, Tzr);
+yeccpars2_271(_, _, _, _, T, _, _) ->
+ yeccerror(T).
%% yeccpars2_272: see yeccpars2_181
@@ -3020,12 +3120,16 @@ yeccpars2_274(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_expr_900(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_275(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 276, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 276, Ss, Stack, T, Ts, Tzr);
+yeccpars2_275(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_276(S, '.', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 278, Ss, Stack, T, Ts, Tzr);
yeccpars2_276(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 214, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 214, Ss, Stack, T, Ts, Tzr);
+yeccpars2_276(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_277(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_|Nss] = Ss,
@@ -3033,7 +3137,9 @@ yeccpars2_277(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_record_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_278(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 279, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 279, Ss, Stack, T, Ts, Tzr);
+yeccpars2_278(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_279(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_,_|Nss] = Ss,
@@ -3051,12 +3157,16 @@ yeccpars2_281(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_expr_600(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_282(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 283, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 283, Ss, Stack, T, Ts, Tzr);
+yeccpars2_282(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_283(S, '.', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 285, Ss, Stack, T, Ts, Tzr);
yeccpars2_283(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 214, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 214, Ss, Stack, T, Ts, Tzr);
+yeccpars2_283(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_284(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_|Nss] = Ss,
@@ -3064,7 +3174,9 @@ yeccpars2_284(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_record_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_285(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 286, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 286, Ss, Stack, T, Ts, Tzr);
+yeccpars2_285(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_286(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_,_|Nss] = Ss,
@@ -3074,7 +3186,9 @@ yeccpars2_286(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_287(S, '->', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 90, Ss, Stack, T, Ts, Tzr);
yeccpars2_287(S, ':-', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 290, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 290, Ss, Stack, T, Ts, Tzr);
+yeccpars2_287(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_288(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_|Nss] = Ss,
@@ -3121,7 +3235,9 @@ yeccpars2_292(S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_293(S, '(', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 296, Ss, Stack, T, Ts, Tzr);
yeccpars2_293(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 297, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 297, Ss, Stack, T, Ts, Tzr);
+yeccpars2_293(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_294(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -3129,10 +3245,14 @@ yeccpars2_294(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_attribute(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_295(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 310, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 310, Ss, Stack, T, Ts, Tzr);
+yeccpars2_295(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_296(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 297, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 297, Ss, Stack, T, Ts, Tzr);
+yeccpars2_296(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_297(S, '/', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 298, Ss, Stack, T, Ts, Tzr);
@@ -3142,10 +3262,14 @@ yeccpars2_297(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_spec_fun(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_298(S, integer, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 304, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 304, Ss, Stack, T, Ts, Tzr);
+yeccpars2_298(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_299(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 300, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 300, Ss, Stack, T, Ts, Tzr);
+yeccpars2_299(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_300(S, '/', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 301, Ss, Stack, T, Ts, Tzr);
@@ -3155,10 +3279,14 @@ yeccpars2_300(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_spec_fun(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_301(S, integer, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 302, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 302, Ss, Stack, T, Ts, Tzr);
+yeccpars2_301(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_302(S, '::', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 303, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 303, Ss, Stack, T, Ts, Tzr);
+yeccpars2_302(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_303(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_,_,_|Nss] = Ss,
@@ -3166,7 +3294,9 @@ yeccpars2_303(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_spec_fun(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_304(S, '::', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 305, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 305, Ss, Stack, T, Ts, Tzr);
+yeccpars2_304(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_305(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_|Nss] = Ss,
@@ -3176,7 +3306,9 @@ yeccpars2_305(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
%% yeccpars2_306: see yeccpars2_295
yeccpars2_307(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 423, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 423, Ss, Stack, T, Ts, Tzr);
+yeccpars2_307(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_308(S, ';', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 421, Ss, Stack, T, Ts, Tzr);
@@ -3219,7 +3351,9 @@ yeccpars2_cont_310(S, 'fun', Ss, Stack, T, Ts, Tzr) ->
yeccpars2_cont_310(S, integer, Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 328, Ss, Stack, T, Ts, Tzr);
yeccpars2_cont_310(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 330, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 330, Ss, Stack, T, Ts, Tzr);
+yeccpars2_cont_310(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_311(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_type_400(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
@@ -3269,7 +3403,9 @@ yeccpars2_315(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_type_500(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_316(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 398, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 398, Ss, Stack, T, Ts, Tzr);
+yeccpars2_316(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_317(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_top_type(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
@@ -3289,7 +3425,9 @@ yeccpars2_320(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_type(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_321(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 384, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 384, Ss, Stack, T, Ts, Tzr);
+yeccpars2_321(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_322(S, '+', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 47, Ss, Stack, T, Ts, Tzr);
@@ -3305,12 +3443,16 @@ yeccpars2_322(S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_cont_310(S, Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_323(S, '->', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 380, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 380, Ss, Stack, T, Ts, Tzr);
+yeccpars2_323(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_324(S, '>>', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 365, Ss, Stack, T, Ts, Tzr);
yeccpars2_324(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 366, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 366, Ss, Stack, T, Ts, Tzr);
+yeccpars2_324(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_325(S, '+', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 47, Ss, Stack, T, Ts, Tzr);
@@ -3335,7 +3477,9 @@ yeccpars2_326(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_type(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_327(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 337, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 337, Ss, Stack, T, Ts, Tzr);
+yeccpars2_327(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_328(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_type(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
@@ -3361,7 +3505,9 @@ yeccpars2_330(S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_cont_310(S, Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_331(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 333, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 333, Ss, Stack, T, Ts, Tzr);
+yeccpars2_331(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_332(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_|Nss] = Ss,
@@ -3397,10 +3543,14 @@ yeccpars2_336(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_337(S, '(', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 340, Ss, Stack, T, Ts, Tzr);
yeccpars2_337(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 341, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 341, Ss, Stack, T, Ts, Tzr);
+yeccpars2_337(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_338(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 346, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 346, Ss, Stack, T, Ts, Tzr);
+yeccpars2_338(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_339(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_fun_type_100(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
@@ -3428,10 +3578,14 @@ yeccpars2_341(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_342(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 343, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 343, Ss, Stack, T, Ts, Tzr);
+yeccpars2_342(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_343(S, '->', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 344, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 344, Ss, Stack, T, Ts, Tzr);
+yeccpars2_343(_, _, _, _, T, _, _) ->
+ yeccerror(T).
%% yeccpars2_344: see yeccpars2_322
@@ -3461,10 +3615,14 @@ yeccpars2_347(S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_cont_310(S, Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_348(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 349, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 349, Ss, Stack, T, Ts, Tzr);
+yeccpars2_348(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_349(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 350, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 350, Ss, Stack, T, Ts, Tzr);
+yeccpars2_349(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_350(S, ')', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 352, Ss, Stack, T, Ts, Tzr);
@@ -3482,7 +3640,9 @@ yeccpars2_350(S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_cont_310(S, Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_351(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 353, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 353, Ss, Stack, T, Ts, Tzr);
+yeccpars2_351(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_352(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_,_|Nss] = Ss,
@@ -3495,7 +3655,9 @@ yeccpars2_353(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_354(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 356, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 356, Ss, Stack, T, Ts, Tzr);
+yeccpars2_354(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_355(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -3510,7 +3672,9 @@ yeccpars2_356(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_357(S, ',', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 359, Ss, Stack, T, Ts, Tzr);
yeccpars2_357(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 360, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 360, Ss, Stack, T, Ts, Tzr);
+yeccpars2_357(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_358(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_|Nss] = Ss,
@@ -3518,7 +3682,9 @@ yeccpars2_358(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_359(S, '...', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 361, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 361, Ss, Stack, T, Ts, Tzr);
+yeccpars2_359(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_360(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -3526,7 +3692,9 @@ yeccpars2_360(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_361(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 362, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 362, Ss, Stack, T, Ts, Tzr);
+yeccpars2_361(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_362(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_,_|Nss] = Ss,
@@ -3534,12 +3702,16 @@ yeccpars2_362(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_363(S, '>>', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 379, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 379, Ss, Stack, T, Ts, Tzr);
+yeccpars2_363(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_364(S, ',', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 372, Ss, Stack, T, Ts, Tzr);
yeccpars2_364(S, '>>', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 373, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 373, Ss, Stack, T, Ts, Tzr);
+yeccpars2_364(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_365(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_|Nss] = Ss,
@@ -3547,7 +3719,9 @@ yeccpars2_365(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_binary_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_366(S, ':', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 367, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 367, Ss, Stack, T, Ts, Tzr);
+yeccpars2_366(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_367(S, var, Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 369, Ss, Stack, T, Ts, Tzr);
@@ -3572,7 +3746,9 @@ yeccpars2_371(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_bin_unit_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_372(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 375, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 375, Ss, Stack, T, Ts, Tzr);
+yeccpars2_372(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_373(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -3580,16 +3756,24 @@ yeccpars2_373(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_binary_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_374(S, '>>', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 378, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 378, Ss, Stack, T, Ts, Tzr);
+yeccpars2_374(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_375(S, ':', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 376, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 376, Ss, Stack, T, Ts, Tzr);
+yeccpars2_375(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_376(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 377, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 377, Ss, Stack, T, Ts, Tzr);
+yeccpars2_376(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_377(S, '*', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 370, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 370, Ss, Stack, T, Ts, Tzr);
+yeccpars2_377(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_378(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_,_|Nss] = Ss,
@@ -3609,7 +3793,9 @@ yeccpars2_381(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_fun_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_382(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 383, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 383, Ss, Stack, T, Ts, Tzr);
+yeccpars2_382(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_383(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -3617,15 +3803,21 @@ yeccpars2_383(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_384(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 385, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 385, Ss, Stack, T, Ts, Tzr);
+yeccpars2_384(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_385(S, atom, Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 388, Ss, Stack, T, Ts, Tzr);
yeccpars2_385(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 389, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 389, Ss, Stack, T, Ts, Tzr);
+yeccpars2_385(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_386(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 394, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 394, Ss, Stack, T, Ts, Tzr);
+yeccpars2_386(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_387(S, ',', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 392, Ss, Stack, T, Ts, Tzr);
@@ -3634,7 +3826,9 @@ yeccpars2_387(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_field_types(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
yeccpars2_388(S, '::', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 390, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 390, Ss, Stack, T, Ts, Tzr);
+yeccpars2_388(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_389(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_|Nss] = Ss,
@@ -3649,7 +3843,9 @@ yeccpars2_391(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_field_type(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_392(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 388, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 388, Ss, Stack, T, Ts, Tzr);
+yeccpars2_392(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_393(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -3674,7 +3870,9 @@ yeccpars2_397(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_top_types(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_398(S, '->', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 399, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 399, Ss, Stack, T, Ts, Tzr);
+yeccpars2_398(_, _, _, _, T, _, _) ->
+ yeccerror(T).
%% yeccpars2_399: see yeccpars2_322
@@ -3742,7 +3940,9 @@ yeccpars2_408(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_409(S, atom, Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 412, Ss, Stack, T, Ts, Tzr);
yeccpars2_409(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 413, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 413, Ss, Stack, T, Ts, Tzr);
+yeccpars2_409(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_410(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -3756,10 +3956,14 @@ yeccpars2_411(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_type_guards(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
yeccpars2_412(S, '(', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 416, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 416, Ss, Stack, T, Ts, Tzr);
+yeccpars2_412(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_413(S, '::', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 414, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 414, Ss, Stack, T, Ts, Tzr);
+yeccpars2_413(_, _, _, _, T, _, _) ->
+ yeccerror(T).
%% yeccpars2_414: see yeccpars2_322
@@ -3771,7 +3975,9 @@ yeccpars2_415(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
%% yeccpars2_416: see yeccpars2_322
yeccpars2_417(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 418, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 418, Ss, Stack, T, Ts, Tzr);
+yeccpars2_417(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_418(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_,_|Nss] = Ss,
@@ -3823,14 +4029,18 @@ yeccpars2_427(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
%% yeccpars2_428: see yeccpars2_45
yeccpars2_429(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 449, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 449, Ss, Stack, T, Ts, Tzr);
+yeccpars2_429(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_430(S, ')', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 210, Ss, Stack, T, Ts, Tzr);
yeccpars2_430(S, ',', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 431, Ss, Stack, T, Ts, Tzr);
yeccpars2_430(S, '::', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 432, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 432, Ss, Stack, T, Ts, Tzr);
+yeccpars2_430(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_431(S, '#', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 44, Ss, Stack, T, Ts, Tzr);
@@ -3870,12 +4080,16 @@ yeccpars2_434(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_typed_attr_val(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_435(S, ')', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 448, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 448, Ss, Stack, T, Ts, Tzr);
+yeccpars2_435(_, _, _, _, T, _, _) ->
+ yeccerror(T).
%% yeccpars2_436: see yeccpars2_68
yeccpars2_437(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 447, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 447, Ss, Stack, T, Ts, Tzr);
+yeccpars2_437(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_438(S, ',', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 444, Ss, Stack, T, Ts, Tzr);
@@ -3950,7 +4164,9 @@ yeccpars2_453(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_form(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_454(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 456, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 456, Ss, Stack, T, Ts, Tzr);
+yeccpars2_454(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_455(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -3973,7 +4189,9 @@ yeccpars2_459(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_form(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_460(S, atom, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 462, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 462, Ss, Stack, T, Ts, Tzr);
+yeccpars2_460(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_461(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
@@ -3989,7 +4207,9 @@ yeccpars2_463(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_464(464, Cat, [463 | Ss], NewStack, T, Ts, Tzr).
yeccpars2_464(S, ':-', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 290, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 290, Ss, Stack, T, Ts, Tzr);
+yeccpars2_464(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccgoto_add_op(33, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_230(249, Cat, Ss, Stack, T, Ts, Tzr);
@@ -7975,7 +8195,7 @@ yeccpars2_39_(__Stack0) ->
[ __1 ]
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 7978).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8198).
-compile({inline,yeccpars2_46_/1}).
-file("erl_parse.yrl", 434).
yeccpars2_46_(__Stack0) ->
@@ -7984,7 +8204,7 @@ yeccpars2_46_(__Stack0) ->
{ [ ] , ? line ( __1 ) }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 7987).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8207).
-compile({inline,yeccpars2_70_/1}).
-file("erl_parse.yrl", 325).
yeccpars2_70_(__Stack0) ->
@@ -7993,7 +8213,7 @@ yeccpars2_70_(__Stack0) ->
{ tuple , ? line ( __1 ) , [ ] }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 7996).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8216).
-compile({inline,yeccpars2_71_/1}).
-file("erl_parse.yrl", 326).
yeccpars2_71_(__Stack0) ->
@@ -8002,7 +8222,7 @@ yeccpars2_71_(__Stack0) ->
{ tuple , ? line ( __1 ) , __2 }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8005).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8225).
-compile({inline,yeccpars2_73_/1}).
-file("erl_parse.yrl", 408).
yeccpars2_73_(__Stack0) ->
@@ -8034,7 +8254,7 @@ yeccpars2_81_(__Stack0) ->
[ __1 | __3 ]
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8037).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8257).
-compile({inline,yeccpars2_82_/1}).
-file("erl_parse.yrl", 406).
yeccpars2_82_(__Stack0) ->
@@ -8067,7 +8287,7 @@ yeccpars2_88_(__Stack0) ->
[ __1 | __3 ]
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8070).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8290).
-compile({inline,yeccpars2_89_/1}).
-file("erl_parse.yrl", 381).
yeccpars2_89_(__Stack0) ->
@@ -8106,7 +8326,7 @@ yeccpars2_98_(__Stack0) ->
[ ]
end | __Stack0].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8109).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8329).
-compile({inline,yeccpars2_100_/1}).
-file("erl_parse.yrl", 427).
yeccpars2_100_(__Stack0) ->
@@ -8123,7 +8343,7 @@ yeccpars2_102_(__Stack0) ->
[ ]
end | __Stack0].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8126).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8346).
-compile({inline,yeccpars2_104_/1}).
-file("erl_parse.yrl", 424).
yeccpars2_104_(__Stack0) ->
@@ -8133,7 +8353,7 @@ yeccpars2_104_(__Stack0) ->
{ clause , L , [ { tuple , L , [ __1 , __3 , { var , L , '_' } ] } ] , __4 , __5 }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8136).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8356).
-compile({inline,yeccpars2_106_/1}).
-file("erl_parse.yrl", 421).
yeccpars2_106_(__Stack0) ->
@@ -8175,7 +8395,7 @@ yeccpars2_114_(__Stack0) ->
{ [ ] , __2 }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8178).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8398).
-compile({inline,yeccpars2_115_/1}).
-file("erl_parse.yrl", 452).
yeccpars2_115_(__Stack0) ->
@@ -8184,7 +8404,7 @@ yeccpars2_115_(__Stack0) ->
{ string , ? line ( __1 ) , element ( 3 , __1 ) ++ element ( 3 , __2 ) }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8187).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8407).
-compile({inline,yeccpars2_120_/1}).
-file("erl_parse.yrl", 386).
yeccpars2_120_(__Stack0) ->
@@ -8193,7 +8413,7 @@ yeccpars2_120_(__Stack0) ->
{ 'receive' , ? line ( __1 ) , [ ] , __3 , __4 }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8196).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8416).
-compile({inline,yeccpars2_122_/1}).
-file("erl_parse.yrl", 384).
yeccpars2_122_(__Stack0) ->
@@ -8202,7 +8422,7 @@ yeccpars2_122_(__Stack0) ->
{ 'receive' , ? line ( __1 ) , __2 }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8205).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8425).
-compile({inline,yeccpars2_125_/1}).
-file("erl_parse.yrl", 388).
yeccpars2_125_(__Stack0) ->
@@ -8219,7 +8439,7 @@ yeccpars2_131_(__Stack0) ->
[ __1 ]
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8222).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8442).
-compile({inline,yeccpars2_135_/1}).
-file("erl_parse.yrl", 323).
yeccpars2_135_(__Stack0) ->
@@ -8228,7 +8448,7 @@ yeccpars2_135_(__Stack0) ->
{ b_generate , ? line ( __2 ) , __1 , __3 }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8231).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8451).
-compile({inline,yeccpars2_137_/1}).
-file("erl_parse.yrl", 322).
yeccpars2_137_(__Stack0) ->
@@ -8245,7 +8465,7 @@ yeccpars2_139_(__Stack0) ->
[ __1 | __3 ]
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8248).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8468).
-compile({inline,yeccpars2_140_/1}).
-file("erl_parse.yrl", 315).
yeccpars2_140_(__Stack0) ->
@@ -8254,7 +8474,7 @@ yeccpars2_140_(__Stack0) ->
{ lc , ? line ( __1 ) , __2 , __4 }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8257).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8477).
-compile({inline,yeccpars2_141_/1}).
-file("erl_parse.yrl", 431).
yeccpars2_141_(__Stack0) ->
@@ -8271,7 +8491,7 @@ yeccpars2_143_(__Stack0) ->
[ __1 ]
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8274).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8494).
-compile({inline,yeccpars2_145_/1}).
-file("erl_parse.yrl", 371).
yeccpars2_145_(__Stack0) ->
@@ -8288,7 +8508,7 @@ yeccpars2_147_(__Stack0) ->
[ __1 | __3 ]
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8291).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8511).
-compile({inline,yeccpars2_148_/1}).
-file("erl_parse.yrl", 365).
yeccpars2_148_(__Stack0) ->
@@ -8312,7 +8532,7 @@ yeccpars2_151_(__Stack0) ->
[ ]
end | __Stack0].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8315).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8535).
-compile({inline,yeccpars2_157_/1}).
-file("erl_parse.yrl", 394).
yeccpars2_157_(__Stack0) ->
@@ -8321,7 +8541,7 @@ yeccpars2_157_(__Stack0) ->
{ 'fun' , ? line ( __1 ) , { function , element ( 3 , __2 ) , element ( 3 , __4 ) , element ( 3 , __6 ) } }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8324).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8544).
-compile({inline,yeccpars2_158_/1}).
-file("erl_parse.yrl", 392).
yeccpars2_158_(__Stack0) ->
@@ -8347,7 +8567,7 @@ yeccpars2_162_(__Stack0) ->
[ __1 | __3 ]
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8350).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8570).
-compile({inline,yeccpars2_163_/1}).
-file("erl_parse.yrl", 396).
yeccpars2_163_(__Stack0) ->
@@ -8356,7 +8576,7 @@ yeccpars2_163_(__Stack0) ->
build_fun ( ? line ( __1 ) , __2 )
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8359).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8579).
-compile({inline,yeccpars2_164_/1}).
-file("erl_parse.yrl", 214).
yeccpars2_164_(__Stack0) ->
@@ -8365,7 +8585,7 @@ yeccpars2_164_(__Stack0) ->
{ 'catch' , ? line ( __1 ) , __2 }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8368).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8588).
-compile({inline,yeccpars2_168_/1}).
-file("erl_parse.yrl", 375).
yeccpars2_168_(__Stack0) ->
@@ -8374,7 +8594,7 @@ yeccpars2_168_(__Stack0) ->
{ 'case' , ? line ( __1 ) , __2 , __4 }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8377).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8597).
-compile({inline,yeccpars2_170_/1}).
-file("erl_parse.yrl", 270).
yeccpars2_170_(__Stack0) ->
@@ -8383,7 +8603,7 @@ yeccpars2_170_(__Stack0) ->
{ block , ? line ( __1 ) , __2 }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8386).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8606).
-compile({inline,yeccpars2_172_/1}).
-file("erl_parse.yrl", 279).
yeccpars2_172_(__Stack0) ->
@@ -8392,7 +8612,7 @@ yeccpars2_172_(__Stack0) ->
{ nil , ? line ( __1 ) }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8395).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8615).
-compile({inline,yeccpars2_173_/1}).
-file("erl_parse.yrl", 280).
yeccpars2_173_(__Stack0) ->
@@ -8401,7 +8621,7 @@ yeccpars2_173_(__Stack0) ->
{ cons , ? line ( __1 ) , __2 , __3 }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8404).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8624).
-compile({inline,yeccpars2_175_/1}).
-file("erl_parse.yrl", 282).
yeccpars2_175_(__Stack0) ->
@@ -8418,7 +8638,7 @@ yeccpars2_178_(__Stack0) ->
__2
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8421).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8641).
-compile({inline,yeccpars2_180_/1}).
-file("erl_parse.yrl", 284).
yeccpars2_180_(__Stack0) ->
@@ -8442,7 +8662,7 @@ yeccpars2_186_(__Stack0) ->
[ __1 ]
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8445).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8665).
-compile({inline,yeccpars2_187_/1}).
-file("erl_parse.yrl", 287).
yeccpars2_187_(__Stack0) ->
@@ -8459,7 +8679,7 @@ yeccpars2_189_(__Stack0) ->
[ __1 | __3 ]
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8462).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8682).
-compile({inline,yeccpars2_190_/1}).
-file("erl_parse.yrl", 288).
yeccpars2_190_(__Stack0) ->
@@ -8468,7 +8688,7 @@ yeccpars2_190_(__Stack0) ->
{ bin , ? line ( __1 ) , __2 }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8471).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8691).
-compile({inline,yeccpars2_193_/1}).
-file("erl_parse.yrl", 317).
yeccpars2_193_(__Stack0) ->
@@ -8492,7 +8712,7 @@ yeccpars2_197_(__Stack0) ->
__2
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8495).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8715).
-compile({inline,yeccpars2_198_/1}).
-file("erl_parse.yrl", 294).
yeccpars2_198_(__Stack0) ->
@@ -8541,7 +8761,7 @@ yeccpars2_206_(__Stack0) ->
[ __1 | __3 ]
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8544).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8764).
-compile({inline,yeccpars2_207_/1}).
-file("erl_parse.yrl", 296).
yeccpars2_207_(__Stack0) ->
@@ -8550,7 +8770,7 @@ yeccpars2_207_(__Stack0) ->
? mkop1 ( __1 , __2 )
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8553).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8773).
-compile({inline,yeccpars2_208_/1}).
-file("erl_parse.yrl", 256).
yeccpars2_208_(__Stack0) ->
@@ -8567,7 +8787,7 @@ yeccpars2_210_(__Stack0) ->
__2
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8570).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8790).
-compile({inline,yeccpars2_212_/1}).
-file("erl_parse.yrl", 340).
yeccpars2_212_(__Stack0) ->
@@ -8592,7 +8812,7 @@ yeccpars2_219_(__Stack0) ->
[ ]
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8595).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8815).
-compile({inline,yeccpars2_221_/1}).
-file("erl_parse.yrl", 356).
yeccpars2_221_(__Stack0) ->
@@ -8601,7 +8821,7 @@ yeccpars2_221_(__Stack0) ->
{ record_field , ? line ( __1 ) , __1 , __3 }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8604).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8824).
-compile({inline,yeccpars2_223_/1}).
-file("erl_parse.yrl", 357).
yeccpars2_223_(__Stack0) ->
@@ -8626,7 +8846,7 @@ yeccpars2_226_(__Stack0) ->
__2
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8629).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8849).
-compile({inline,yeccpars2_227_/1}).
-file("erl_parse.yrl", 338).
yeccpars2_227_(__Stack0) ->
@@ -8643,7 +8863,7 @@ yeccpars2_229_(__Stack0) ->
[ __1 | __3 ]
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8646).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8866).
-compile({inline,yeccpars2_232_/1}).
-file("erl_parse.yrl", 217).
yeccpars2_232_(__Stack0) ->
@@ -8652,7 +8872,7 @@ yeccpars2_232_(__Stack0) ->
{ match , ? line ( __2 ) , __1 , __3 }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8655).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8875).
-compile({inline,yeccpars2_233_/1}).
-file("erl_parse.yrl", 218).
yeccpars2_233_(__Stack0) ->
@@ -8661,7 +8881,7 @@ yeccpars2_233_(__Stack0) ->
? mkop2 ( __1 , __2 , __3 )
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8664).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8884).
-compile({inline,yeccpars2_235_/1}).
-file("erl_parse.yrl", 221).
yeccpars2_235_(__Stack0) ->
@@ -8670,7 +8890,7 @@ yeccpars2_235_(__Stack0) ->
? mkop2 ( __1 , __2 , __3 )
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8673).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8893).
-compile({inline,yeccpars2_237_/1}).
-file("erl_parse.yrl", 224).
yeccpars2_237_(__Stack0) ->
@@ -8679,7 +8899,7 @@ yeccpars2_237_(__Stack0) ->
? mkop2 ( __1 , __2 , __3 )
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8682).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8902).
-compile({inline,yeccpars2_247_/1}).
-file("erl_parse.yrl", 228).
yeccpars2_247_(__Stack0) ->
@@ -8688,7 +8908,7 @@ yeccpars2_247_(__Stack0) ->
? mkop2 ( __1 , __2 , __3 )
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8691).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8911).
-compile({inline,yeccpars2_260_/1}).
-file("erl_parse.yrl", 236).
yeccpars2_260_(__Stack0) ->
@@ -8697,7 +8917,7 @@ yeccpars2_260_(__Stack0) ->
? mkop2 ( __1 , __2 , __3 )
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8700).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8920).
-compile({inline,yeccpars2_268_/1}).
-file("erl_parse.yrl", 240).
yeccpars2_268_(__Stack0) ->
@@ -8706,7 +8926,7 @@ yeccpars2_268_(__Stack0) ->
? mkop2 ( __1 , __2 , __3 )
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8709).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8929).
-compile({inline,yeccpars2_269_/1}).
-file("erl_parse.yrl", 232).
yeccpars2_269_(__Stack0) ->
@@ -8715,7 +8935,7 @@ yeccpars2_269_(__Stack0) ->
? mkop2 ( __1 , __2 , __3 )
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8718).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8938).
-compile({inline,yeccpars2_270_/1}).
-file("erl_parse.yrl", 362).
yeccpars2_270_(__Stack0) ->
@@ -8724,7 +8944,7 @@ yeccpars2_270_(__Stack0) ->
{ call , ? line ( __1 ) , __1 , element ( 1 , __2 ) }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8727).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8947).
-compile({inline,yeccpars2_273_/1}).
-file("erl_parse.yrl", 252).
yeccpars2_273_(__Stack0) ->
@@ -8733,7 +8953,7 @@ yeccpars2_273_(__Stack0) ->
{ remote , ? line ( __2 ) , __1 , __3 }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8736).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8956).
-compile({inline,yeccpars2_274_/1}).
-file("erl_parse.yrl", 258).
yeccpars2_274_(__Stack0) ->
@@ -8742,7 +8962,7 @@ yeccpars2_274_(__Stack0) ->
{ record_field , ? line ( __2 ) , __1 , __3 }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8745).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8965).
-compile({inline,yeccpars2_277_/1}).
-file("erl_parse.yrl", 344).
yeccpars2_277_(__Stack0) ->
@@ -8751,7 +8971,7 @@ yeccpars2_277_(__Stack0) ->
{ record , ? line ( __2 ) , __1 , element ( 3 , __3 ) , __4 }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8754).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8974).
-compile({inline,yeccpars2_279_/1}).
-file("erl_parse.yrl", 342).
yeccpars2_279_(__Stack0) ->
@@ -8760,7 +8980,7 @@ yeccpars2_279_(__Stack0) ->
{ record_field , ? line ( __2 ) , __1 , element ( 3 , __3 ) , __5 }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8763).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8983).
-compile({inline,yeccpars2_280_/1}).
-file("erl_parse.yrl", 435).
yeccpars2_280_(__Stack0) ->
@@ -8769,7 +8989,7 @@ yeccpars2_280_(__Stack0) ->
{ __2 , ? line ( __1 ) }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8772).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8992).
-compile({inline,yeccpars2_281_/1}).
-file("erl_parse.yrl", 244).
yeccpars2_281_(__Stack0) ->
@@ -8778,7 +8998,7 @@ yeccpars2_281_(__Stack0) ->
? mkop1 ( __1 , __2 )
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8781).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9001).
-compile({inline,yeccpars2_284_/1}).
-file("erl_parse.yrl", 348).
yeccpars2_284_(__Stack0) ->
@@ -8787,7 +9007,7 @@ yeccpars2_284_(__Stack0) ->
{ record , ? line ( __2 ) , __1 , element ( 3 , __3 ) , __4 }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8790).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9010).
-compile({inline,yeccpars2_286_/1}).
-file("erl_parse.yrl", 346).
yeccpars2_286_(__Stack0) ->
@@ -8796,7 +9016,7 @@ yeccpars2_286_(__Stack0) ->
{ record_field , ? line ( __2 ) , __1 , element ( 3 , __3 ) , __5 }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8799).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9019).
-compile({inline,yeccpars2_288_/1}).
-file("erl_parse.yrl", 493).
yeccpars2_288_(__Stack0) ->
@@ -8805,7 +9025,7 @@ yeccpars2_288_(__Stack0) ->
{ clause , ? line ( __1 ) , element ( 3 , __1 ) , __2 , __3 , __4 }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8808).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9028).
-compile({inline,yeccpars2_289_/1}).
-file("erl_parse.yrl", 203).
yeccpars2_289_(__Stack0) ->
@@ -8870,7 +9090,7 @@ yeccpars2_318_(__Stack0) ->
[ __1 ]
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8873).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9093).
-compile({inline,yeccpars2_332_/1}).
-file("erl_parse.yrl", 152).
yeccpars2_332_(__Stack0) ->
@@ -8879,7 +9099,7 @@ yeccpars2_332_(__Stack0) ->
{ type , ? line ( __1 ) , tuple , [ ] }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8882).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9102).
-compile({inline,yeccpars2_333_/1}).
-file("erl_parse.yrl", 153).
yeccpars2_333_(__Stack0) ->
@@ -8888,7 +9108,7 @@ yeccpars2_333_(__Stack0) ->
{ type , ? line ( __1 ) , tuple , __2 }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8891).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9111).
-compile({inline,yeccpars2_335_/1}).
-file("erl_parse.yrl", 116).
yeccpars2_335_(__Stack0) ->
@@ -8897,7 +9117,7 @@ yeccpars2_335_(__Stack0) ->
{ ann_type , ? line ( __1 ) , [ __1 , __3 ] }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8900).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9120).
-compile({inline,yeccpars2_341_/1}).
-file("erl_parse.yrl", 159).
yeccpars2_341_(__Stack0) ->
@@ -8906,7 +9126,7 @@ yeccpars2_341_(__Stack0) ->
{ type , ? line ( __1 ) , 'fun' , [ ] }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8909).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9129).
-compile({inline,yeccpars2_345_/1}).
-file("erl_parse.yrl", 163).
yeccpars2_345_(__Stack0) ->
@@ -8924,7 +9144,7 @@ yeccpars2_346_(__Stack0) ->
__3
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8927).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9147).
-compile({inline,yeccpars2_352_/1}).
-file("erl_parse.yrl", 144).
yeccpars2_352_(__Stack0) ->
@@ -8934,7 +9154,7 @@ yeccpars2_352_(__Stack0) ->
[ __1 , __3 , [ ] ] }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8937).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9157).
-compile({inline,yeccpars2_353_/1}).
-file("erl_parse.yrl", 146).
yeccpars2_353_(__Stack0) ->
@@ -8952,7 +9172,7 @@ yeccpars2_355_(__Stack0) ->
build_gen_type ( __1 )
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8955).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9175).
-compile({inline,yeccpars2_356_/1}).
-file("erl_parse.yrl", 142).
yeccpars2_356_(__Stack0) ->
@@ -8962,7 +9182,7 @@ yeccpars2_356_(__Stack0) ->
normalise ( __1 ) , __3 }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8965).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9185).
-compile({inline,yeccpars2_358_/1}).
-file("erl_parse.yrl", 148).
yeccpars2_358_(__Stack0) ->
@@ -8971,7 +9191,7 @@ yeccpars2_358_(__Stack0) ->
{ type , ? line ( __1 ) , nil , [ ] }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8974).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9194).
-compile({inline,yeccpars2_360_/1}).
-file("erl_parse.yrl", 149).
yeccpars2_360_(__Stack0) ->
@@ -8980,7 +9200,7 @@ yeccpars2_360_(__Stack0) ->
{ type , ? line ( __1 ) , list , [ __2 ] }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8983).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9203).
-compile({inline,yeccpars2_362_/1}).
-file("erl_parse.yrl", 150).
yeccpars2_362_(__Stack0) ->
@@ -8990,7 +9210,7 @@ yeccpars2_362_(__Stack0) ->
nonempty_list , [ __2 ] }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 8993).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9213).
-compile({inline,yeccpars2_365_/1}).
-file("erl_parse.yrl", 179).
yeccpars2_365_(__Stack0) ->
@@ -9017,7 +9237,7 @@ yeccpars2_371_(__Stack0) ->
build_bin_type ( [ __1 , __3 ] , __5 )
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9020).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9240).
-compile({inline,yeccpars2_373_/1}).
-file("erl_parse.yrl", 182).
yeccpars2_373_(__Stack0) ->
@@ -9027,7 +9247,7 @@ yeccpars2_373_(__Stack0) ->
[ __2 , abstract ( 0 , ? line ( __1 ) ) ] }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9030).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9250).
-compile({inline,yeccpars2_378_/1}).
-file("erl_parse.yrl", 187).
yeccpars2_378_(__Stack0) ->
@@ -9036,7 +9256,7 @@ yeccpars2_378_(__Stack0) ->
{ type , ? line ( __1 ) , binary , [ __2 , __4 ] }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9039).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9259).
-compile({inline,yeccpars2_379_/1}).
-file("erl_parse.yrl", 184).
yeccpars2_379_(__Stack0) ->
@@ -9046,7 +9266,7 @@ yeccpars2_379_(__Stack0) ->
[ abstract ( 0 , ? line ( __1 ) ) , __2 ] }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9049).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9269).
-compile({inline,yeccpars2_381_/1}).
-file("erl_parse.yrl", 167).
yeccpars2_381_(__Stack0) ->
@@ -9056,7 +9276,7 @@ yeccpars2_381_(__Stack0) ->
[ { type , ? line ( __1 ) , product , [ ] } , __4 ] }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9059).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9279).
-compile({inline,yeccpars2_383_/1}).
-file("erl_parse.yrl", 138).
yeccpars2_383_(__Stack0) ->
@@ -9073,7 +9293,7 @@ yeccpars2_387_(__Stack0) ->
[ __1 ]
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9076).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9296).
-compile({inline,yeccpars2_389_/1}).
-file("erl_parse.yrl", 154).
yeccpars2_389_(__Stack0) ->
@@ -9082,7 +9302,7 @@ yeccpars2_389_(__Stack0) ->
{ type , ? line ( __1 ) , record , [ __2 ] }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9085).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9305).
-compile({inline,yeccpars2_391_/1}).
-file("erl_parse.yrl", 176).
yeccpars2_391_(__Stack0) ->
@@ -9100,7 +9320,7 @@ yeccpars2_393_(__Stack0) ->
[ __1 | __3 ]
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9103).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9323).
-compile({inline,yeccpars2_394_/1}).
-file("erl_parse.yrl", 155).
yeccpars2_394_(__Stack0) ->
@@ -9110,7 +9330,7 @@ yeccpars2_394_(__Stack0) ->
record , [ __2 | __4 ] }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9113).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9333).
-compile({inline,yeccpars2_395_/1}).
-file("erl_parse.yrl", 135).
yeccpars2_395_(__Stack0) ->
@@ -9127,7 +9347,7 @@ yeccpars2_397_(__Stack0) ->
[ __1 | __3 ]
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9130).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9350).
-compile({inline,yeccpars2_400_/1}).
-file("erl_parse.yrl", 170).
yeccpars2_400_(__Stack0) ->
@@ -9145,7 +9365,7 @@ yeccpars2_402_(__Stack0) ->
lift_unions ( __1 , __3 )
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9148).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9368).
-compile({inline,yeccpars2_405_/1}).
-file("erl_parse.yrl", 122).
yeccpars2_405_(__Stack0) ->
@@ -9156,7 +9376,7 @@ yeccpars2_405_(__Stack0) ->
skip_paren ( __3 ) ] }
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9159).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9379).
-compile({inline,yeccpars2_406_/1}).
-file("erl_parse.yrl", 127).
yeccpars2_406_(__Stack0) ->
@@ -9166,7 +9386,7 @@ yeccpars2_406_(__Stack0) ->
__2 , skip_paren ( __3 ) )
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9169).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9389).
-compile({inline,yeccpars2_408_/1}).
-file("erl_parse.yrl", 131).
yeccpars2_408_(__Stack0) ->
@@ -9176,7 +9396,7 @@ yeccpars2_408_(__Stack0) ->
__2 , skip_paren ( __3 ) )
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9179).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9399).
-compile({inline,yeccpars2_410_/1}).
-file("erl_parse.yrl", 103).
yeccpars2_410_(__Stack0) ->
@@ -9202,7 +9422,7 @@ yeccpars2_415_(__Stack0) ->
build_def ( __1 , __3 )
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9205).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9425).
-compile({inline,yeccpars2_418_/1}).
-file("erl_parse.yrl", 109).
yeccpars2_418_(__Stack0) ->
@@ -9332,7 +9552,7 @@ yeccpars2_446_(__Stack0) ->
[ __1 | __3 ]
end | __Stack].
--file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9335).
+-file("/ldisk/bjorn/otp/bootstrap/lib/stdlib/egen/erl_parse.erl", 9555).
-compile({inline,yeccpars2_447_/1}).
-file("erl_parse.yrl", 90).
yeccpars2_447_(__Stack0) ->
diff --git a/configure.in b/configure.in
index f9fa34cedf..36b33ec399 100644
--- a/configure.in
+++ b/configure.in
@@ -97,7 +97,7 @@ fi
TARGET=$host
AC_SUBST(TARGET)
-if test X$cross_compiling = Xyes; then
+if test "$cross_compiling" = "yes"; then
CROSS_COMPILING=yes
else
CROSS_COMPILING=no
@@ -106,7 +106,8 @@ AC_SUBST(CROSS_COMPILING)
AC_ARG_ENABLE(bootstrap-only,
-[ --enable-bootstrap-only enable bootstrap only configuration],
+AS_HELP_STRING([--enable-bootstrap-only],
+ [enable bootstrap only configuration]),
[ if test "X$enableval" = "Xyes"; then
BOOTSTRAP_ONLY=yes
else
@@ -192,53 +193,62 @@ AC_MSG_RESULT([$OTP_REL])
AC_SUBST(OTP_REL)
AC_ARG_ENABLE(threads,
-[ --enable-threads enable async thread support
- --disable-threads disable async thread support])
+AS_HELP_STRING([--enable-threads], [enable async thread support])
+AS_HELP_STRING([--disable-threads], [disable async thread support]))
AC_ARG_ENABLE(halfword-emulator,
-[ --enable-halfword-emulator enable halfword emulator (only for 64bit builds)
- --disable-halfword-emulator disable halfword emulator (only for 64bit builds)])
+AS_HELP_STRING([--enable-halfword-emulator],
+ [enable halfword emulator (only for 64bit builds)]))
AC_ARG_ENABLE(smp-support,
-[ --enable-smp-support enable smp support
- --disable-smp-support disable smp support])
+AS_HELP_STRING([--enable-smp-support], [enable smp support])
+AS_HELP_STRING([--disable-smp-support], [disable smp support]))
AC_ARG_WITH(termcap,
-[ --with-termcap use termcap (default)
- --without-termcap do not use any termcap libraries (ncurses,curses,termcap,termlib)])
+AS_HELP_STRING([--with-termcap], [use termcap (default)])
+AS_HELP_STRING([--without-termcap],
+ [do not use any termcap libraries (ncurses,curses,termcap,termlib)]))
AC_ARG_ENABLE(kernel-poll,
-[ --enable-kernel-poll enable kernel poll support])
+AS_HELP_STRING([--enable-kernel-poll], [enable kernel poll support])
+AS_HELP_STRING([--disable-kernel-poll], [disable kernel poll support]))
+
+AC_ARG_ENABLE(sctp,
+AS_HELP_STRING([--enable-sctp], [enable sctp support])
+AS_HELP_STRING([--disable-sctp], [disable sctp support]))
AC_ARG_ENABLE(hipe,
-[ --enable-hipe enable hipe support
- --disable-hipe disable hipe support])
-
+AS_HELP_STRING([--enable-hipe], [enable hipe support])
+AS_HELP_STRING([--disable-hipe], [disable hipe support]))
+
+AC_ARG_ENABLE(native-libs,
+AS_HELP_STRING([--enable-native-libs],
+ [compile Erlang libraries to native code]))
+
AC_ARG_WITH(javac,
-[ --with-javac=JAVAC specify Java compiler to use
- --with-javac use a Java compiler if found (default)
- --without-javac don't use any Java compiler])
+AS_HELP_STRING([--with-javac=JAVAC], [specify Java compiler to use])
+AS_HELP_STRING([--with-javac], [use a Java compiler if found (default)])
+AS_HELP_STRING([--without-javac], [don't use any Java compiler]))
AC_ARG_ENABLE(megaco_flex_scanner_lineno,
-[ --enable-megaco-flex-scanner-lineno enable megaco flex scanner lineno
- --disable-megaco-flex-scanner-lineno disable megaco flex scanner lineno])
+AS_HELP_STRING([--disable-megaco-flex-scanner-lineno],
+ [disable megaco flex scanner lineno]))
AC_ARG_ENABLE(megaco_reentrant_flex_scanner,
-[ --enable-megaco-reentrant-flex-scanner enable reentrans megaco flex scanner
- --disable-megaco-reentrant-flex-scanner disable reentrans megaco flex scanner])
+AS_HELP_STRING([--disable-megaco-reentrant-flex-scanner],
+ [disable reentrant megaco flex scanner]))
AC_ARG_WITH(ssl,
-[ --with-ssl=PATH specify location of OpenSSL include and lib
- --with-ssl use SSL (default)
- --without-ssl don't use SSL])
+AS_HELP_STRING([--with-ssl=PATH], [specify location of OpenSSL include and lib])
+AS_HELP_STRING([--with-ssl], [use SSL (default)])
+AS_HELP_STRING([--without-ssl], [don't use SSL]))
AC_ARG_ENABLE(dynamic-ssl-lib,
-[ --enable-dynamic-ssl-lib force using dynamic openssl libraries
- --disable-dynamic-ssl-lib disable using dynamic openssl libraries])
+AS_HELP_STRING([--disable-dynamic-ssl-lib],
+ [disable using dynamic openssl libraries]))
AC_ARG_ENABLE(shared-zlib,
-[ --enable-shared-zlib enable using shared zlib library
- --disable-shared-zlib disable shared zlib, compile own zlib source (default)])
+AS_HELP_STRING([--enable-shared-zlib], [enable using shared zlib library]))
dnl This functionality has been lost along the way... :(
dnl It could perhaps be nice to reintroduce some day; therefore,
@@ -256,7 +266,8 @@ dnl esac ], erl_mandir='$(erlang_libdir)/man')
dnl AC_SUBST(erl_mandir)
AC_ARG_ENABLE(darwin-universal,
-[ --enable-darwin-universal build universal binaries on darwin i386],
+AS_HELP_STRING([--enable-darwin-universal],
+ [build universal binaries on darwin i386]),
[ case "$enableval" in
no) enable_darwin_universal=no ;;
*) enable_darwin_univeral=yes ;;
@@ -265,7 +276,7 @@ AC_ARG_ENABLE(darwin-universal,
AC_ARG_ENABLE(darwin-64bit,
-[ --enable-darwin-64bit build 64bit binaries on darwin],
+AS_HELP_STRING([--enable-darwin-64bit], [build 64bit binaries on darwin]),
[ case "$enableval" in
no) enable_darwin_64bit=no ;;
*) enable_darwin_64bit=yes ;;
@@ -273,7 +284,8 @@ AC_ARG_ENABLE(darwin-64bit,
],enable_darwin_64bit=no)
AC_ARG_ENABLE(m64-build,
-[ --enable-m64-build build 64bit binaries using the -m64 flag to (g)cc],
+AS_HELP_STRING([--enable-m64-build],
+ [build 64bit binaries using the -m64 flag to (g)cc]),
[ case "$enableval" in
no) enable_m64_build=no ;;
*) enable_m64_build=yes ;;
@@ -281,7 +293,8 @@ AC_ARG_ENABLE(m64-build,
],enable_m64_build=no)
AC_ARG_ENABLE(m32-build,
-[ --enable-m32-build build 32bit binaries using the -m32 flag to (g)cc],
+AS_HELP_STRING([--enable-m32-build],
+ [build 32bit binaries using the -m32 flag to (g)cc]),
[ case "$enableval" in
no) enable_m32_build=no ;;
*)
@@ -293,6 +306,14 @@ AC_ARG_ENABLE(m32-build,
esac
],enable_m32_build=no)
+AC_ARG_ENABLE(ethread-pre-pentium4-compatibility,
+ AS_HELP_STRING([--enable-ethread-pre-pentium4-compatibility],
+ [enable compatibility with x86 processors before pentium 4 (back to 486) in the ethread library]))
+
+AC_ARG_WITH(libatomic_ops,
+ AS_HELP_STRING([--with-libatomic_ops=PATH],
+ [specify and prefer usage of libatomic_ops in the ethread library]))
+
dnl OK, we might have darwin switches off different kinds, lets
dnl check it all before continuing.
TMPSYS=`uname -s`-`uname -m`
diff --git a/erts/aclocal.m4 b/erts/aclocal.m4
index 0fa3fec244..443d8622bf 100644
--- a/erts/aclocal.m4
+++ b/erts/aclocal.m4
@@ -386,14 +386,24 @@ AC_DEFUN(LM_SYS_IPV6,
AC_CACHE_VAL(ac_cv_sys_ipv6_support,
[ok_so_far=yes
AC_TRY_COMPILE([#include <sys/types.h>
-#include <netinet/in.h>],
+#ifdef __WIN32__
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <netinet/in.h>
+#endif],
[struct in6_addr a6; struct sockaddr_in6 s6;], ok_so_far=yes, ok_so_far=no)
if test $ok_so_far = yes; then
ac_cv_sys_ipv6_support=yes
else
AC_TRY_COMPILE([#include <sys/types.h>
-#include <netinet/in.h>],
+#ifdef __WIN32__
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <netinet/in.h>
+#endif],
[struct in_addr6 a6; struct sockaddr_in6 s6;],
ac_cv_sys_ipv6_support=in_addr6, ac_cv_sys_ipv6_support=no)
fi
@@ -521,11 +531,13 @@ if test "X$host_os" = "Xwin32"; then
THR_DEFS="-DWIN32_THREADS"
THR_LIBS=
THR_LIB_NAME=win32_threads
+ THR_LIB_TYPE=win32_threads
else
AC_MSG_RESULT(no)
THR_DEFS=
THR_LIBS=
THR_LIB_NAME=
+ THR_LIB_TYPE=posix_unknown
dnl Try to find POSIX threads
@@ -586,6 +598,7 @@ dnl On ofs1 the '-pthread' switch should be used
AC_MSG_WARN([result yes guessed because of cross compilation])
fi
if test $nptl = yes; then
+ THR_LIB_TYPE=posix_nptl
need_nptl_incldir=no
AC_CHECK_HEADER(nptl/pthread.h,
[need_nptl_incldir=yes
@@ -694,6 +707,7 @@ ERL_INTERNAL_LIBS
ethr_have_native_atomics=no
ethr_have_native_spinlock=no
ETHR_THR_LIB_BASE="$THR_LIB_NAME"
+ETHR_THR_LIB_BASE_TYPE="$THR_LIB_TYPE"
ETHR_DEFS="$THR_DEFS"
ETHR_X_LIBS="$THR_LIBS $ERTS_INTERNAL_X_LIBS"
ETHR_LIBS=
@@ -990,8 +1004,8 @@ case "$THR_LIB_NAME" in
case "$host_cpu" in
sun4u | sparc64 | sun4v)
- ethr_have_native_atomics=yes;;
- i86pc | i386 | i486 | i586 | i686 | x86_64 | amd64)
+ ethr_have_native_atomics=yes;;
+ i86pc | i*86 | x86_64 | amd64)
ethr_have_native_atomics=yes;;
macppc | ppc | "Power Macintosh")
ethr_have_native_atomics=yes;;
@@ -1086,7 +1100,7 @@ test "X$disable_native_ethr_impls" = "Xyes" &&
AC_ARG_ENABLE(prefer-gcc-native-ethr-impls,
AS_HELP_STRING([--enable-prefer-gcc-native-ethr-impls],
- [enable prefer gcc native ethread implementations]),
+ [prefer gcc native ethread implementations]),
[ case "$enableval" in
yes) enable_prefer_gcc_native_ethr_impls=yes ;;
*) enable_prefer_gcc_native_ethr_impls=no ;;
@@ -1095,21 +1109,60 @@ AC_ARG_ENABLE(prefer-gcc-native-ethr-impls,
test $enable_prefer_gcc_native_ethr_impls = yes &&
AC_DEFINE(ETHR_PREFER_GCC_NATIVE_IMPLS, 1, [Define if you prefer gcc native ethread implementations])
+AC_ARG_WITH(libatomic_ops,
+ AS_HELP_STRING([--with-libatomic_ops=PATH],
+ [specify and prefer usage of libatomic_ops in the ethread library]))
+
AC_ARG_ENABLE(ethread-pre-pentium4-compatibility,
AS_HELP_STRING([--enable-ethread-pre-pentium4-compatibility],
[enable compatibility with x86 processors before pentium 4 (back to 486) in the ethread library]),
-[ case "$enableval" in
- yes) enable_ethread_pre_pentium4_compatibility=yes ;;
- *) enable_ethread_pre_pentium4_compatibilit=no ;;
- esac ], enable_ethread_pre_pentium4_compatibilit=no)
+[
+ case "$enable_ethread_pre_pentium4_compatibility" in
+ yes|no) ;;
+ *) enable_ethread_pre_pentium4_compatibility=check;;
+ esac
+],
+[enable_ethread_pre_pentium4_compatibility=check])
+
+test "$cross_compiling" != "yes" || enable_ethread_pre_pentium4_compatibility=no
+
+case "$enable_ethread_pre_pentium4_compatibility-$host_cpu" in
+ check-i86pc | check-i*86)
+ AC_MSG_CHECKING([whether pre pentium 4 compatibility should forced])
+ AC_RUN_IFELSE([
+#if defined(__GNUC__)
+# if defined(ETHR_PREFER_LIBATOMIC_OPS_NATIVE_IMPLS)
+# define CHECK_LIBATOMIC_OPS__
+# else
+# define CHECK_GCC_ASM__
+# endif
+#elif defined(ETHR_HAVE_LIBATOMIC_OPS)
+# define CHECK_LIBATOMIC_OPS__
+#endif
+#if defined(CHECK_LIBATOMIC_OPS__)
+#include "atomic_ops.h"
+#endif
+int main(void)
+{
+#if defined(CHECK_GCC_ASM__)
+ __asm__ __volatile__("mfence" : : : "memory");
+#elif defined(CHECK_LIBATOMIC_OPS__)
+ AO_nop_full();
+#endif
+ return 0;
+}
+ ],
+ [enable_ethread_pre_pentium4_compatibility=no],
+ [enable_ethread_pre_pentium4_compatibility=yes],
+ [enable_ethread_pre_pentium4_compatibility=no])
+ AC_MSG_RESULT([$enable_ethread_pre_pentium4_compatibility]);;
+ *)
+ ;;
+esac
-test $enable_ethread_pre_pentium4_compatibilit = yes &&
+test $enable_ethread_pre_pentium4_compatibility = yes &&
AC_DEFINE(ETHR_PRE_PENTIUM4_COMPAT, 1, [Define if you want compatibilty with x86 processors before pentium4.])
-AC_ARG_WITH(libatomic_ops,
- AS_HELP_STRING([--with-libatomic_ops=PATH],
- [use libatomic_ops with the ethread library]))
-
AC_DEFINE(ETHR_HAVE_ETHREAD_DEFINES, 1, \
[Define if you have all ethread defines])
diff --git a/erts/autoconf/configure.vxworks b/erts/autoconf/configure.vxworks
index 70d7bdbaf2..14fbf766dc 100755
--- a/erts/autoconf/configure.vxworks
+++ b/erts/autoconf/configure.vxworks
@@ -101,7 +101,6 @@ epmd_dir=${ERL_TOP}/erts/epmd/src
os_mon_dir=${ERL_TOP}/lib/os_mon/c_src
orber_dir=${ERL_TOP}/lib/orber/c_src
ic_dir=${ERL_TOP}/lib/ic/c_src
-asn1_dir=${ERL_TOP}/lib/asn1/c_src
internal_tools_dir=${ERL_TOP}
libdir=${ERL_TOP}/lib
tsdir=$libdir/test_server/src
@@ -122,7 +121,6 @@ CONFIG_FILES="${ERL_TOP}/erts/emulator/$host/Makefile
$os_mon_dir/$host/Makefile
$zlibdir/$host/Makefile
$ic_dir/$host/Makefile
- $asn1_dir/$host/Makefile
$runtime_tools_dir/$host/Makefile
$tools_dir/$host/Makefile
$orber_dir/$host/Makefile"
diff --git a/erts/autoconf/vxworks/sed.general b/erts/autoconf/vxworks/sed.general
index f725a6f9ca..551458daf5 100644
--- a/erts/autoconf/vxworks/sed.general
+++ b/erts/autoconf/vxworks/sed.general
@@ -55,12 +55,16 @@ s|@ETHR_LIBS@||
s|@ETHR_LIB_NAME@||
s|@ETHR_DEFS@||
s|@ETHR_THR_LIB_BASE@||
+s|@ETHR_THR_LIB_BASE_DIR@||
s|@EMU_THR_DEFS@||
s|@EMU_THR_LIBS@||
s|@EMU_THR_LIB_NAME@|ethread|
s|@ERTS_ENABLE_KERNEL_POLL@|no|
+s|@ERTS_INTERNAL_X_LIBS@||
s|@cc_root@|/clearcase/otp/|
# Define VxWorks even though cross-compiling.
+s|@CROSS_COMPILING|yes|
+
s|@HCFLAGS@|-DVXWORKS|
s|@HCLIBS@||
s|@ENABLE_ALLOC_TYPE_VARS@||
diff --git a/erts/autoconf/win32.config.cache.static b/erts/autoconf/win32.config.cache.static
index 31dfe510cd..cc33fc09b3 100755
--- a/erts/autoconf/win32.config.cache.static
+++ b/erts/autoconf/win32.config.cache.static
@@ -212,7 +212,6 @@ ac_cv_sizeof_void_p=${ac_cv_sizeof_void_p=4}
ac_cv_struct_exception=${ac_cv_struct_exception=no}
ac_cv_struct_sockaddr_sa_len=${ac_cv_struct_sockaddr_sa_len=no}
ac_cv_struct_tm=${ac_cv_struct_tm=time.h}
-ac_cv_sys_ipv6_support=${ac_cv_sys_ipv6_support=no}
ac_cv_sys_multicast_support=${ac_cv_sys_multicast_support=no}
ac_cv_type_char=${ac_cv_type_char=yes}
ac_cv_type_int=${ac_cv_type_int=yes}
diff --git a/erts/configure.in b/erts/configure.in
index 157163fe0b..8d629c25ae 100644
--- a/erts/configure.in
+++ b/erts/configure.in
@@ -90,6 +90,13 @@ else
host_os=$host
fi
+if test "$cross_compiling" = "yes"; then
+ CROSS_COMPILING=yes
+else
+ CROSS_COMPILING=no
+fi
+AC_SUBST(CROSS_COMPILING)
+
ERL_XCOMP_SYSROOT_INIT
AC_ISC_POSIX
@@ -103,7 +110,8 @@ ENABLE_ALLOC_TYPE_VARS=
AC_SUBST(ENABLE_ALLOC_TYPE_VARS)
AC_ARG_ENABLE(bootstrap-only,
-[ --enable-bootstrap-only enable bootstrap only configuration],
+AS_HELP_STRING([--enable-bootstrap-only],
+ [enable bootstrap only configuration]),
[ if test "X$enableval" = "Xyes"; then
# Disable stuff not necessary in a bootstrap only system in order
# to speed up things by reducing the amount of stuff needing to be
@@ -119,46 +127,46 @@ AC_ARG_ENABLE(bootstrap-only,
])
AC_ARG_ENABLE(threads,
-[ --enable-threads enable async thread support
- --disable-threads disable async thread support],
+AS_HELP_STRING([--enable-threads], [enable async thread support])
+AS_HELP_STRING([--disable-threads], [disable async thread support]),
[ case "$enableval" in
no) enable_threads=no ;;
*) enable_threads=yes ;;
esac ], enable_threads=unknown)
AC_ARG_ENABLE(halfword-emulator,
-[ --enable-halfword-emulator enable halfword emulator (only for 64bit builds)
- --disable-halfword-emulator disable halfword emulator (only for 64bit builds)],
+AS_HELP_STRING([--enable-halfword-emulator],
+ [enable halfword emulator (only for 64bit builds)]),
[ case "$enableval" in
no) enable_halfword_emualtor=no ;;
*) enable_halfword_emulator=yes ;;
esac ], enable_halfword_emulator=unknown)
AC_ARG_ENABLE(smp-support,
-[ --enable-smp-support enable smp support
- --disable-smp-support disable smp support],
+AS_HELP_STRING([--enable-smp-support], [enable smp support])
+AS_HELP_STRING([--disable-smp-support], [disable smp support]),
[ case "$enableval" in
no) enable_smp_support=no ;;
*) enable_smp_support=yes ;;
esac ], enable_smp_support=unknown)
AC_ARG_WITH(termcap,
-[ --with-termcap use termcap (default)
- --without-termcap do not use any termcap libraries (ncurses,curses,termcap,termlib)],
+AS_HELP_STRING([--with-termcap], [use termcap (default)])
+AS_HELP_STRING([--without-termcap],
+ [do not use any termcap libraries (ncurses,curses,termcap,termlib)]),
[],
[with_termcap=yes])
AC_ARG_ENABLE(hybrid-heap,
-[ --enable-hybrid-heap enable hybrid heap
- --disable-hybrid-heap disable hybrid heap],
+AS_HELP_STRING([--enable-hybrid-heap], [enable hybrid heap]),
[ case "$enableval" in
no) enable_hybrid_heap=no ;;
*) enable_hybrid_heap=yes ;;
esac ], enable_hybrid_heap=unknown)
AC_ARG_ENABLE(lock-checking,
-[ --enable-lock-checking enable lock checking],
+AS_HELP_STRING([--enable-lock-checking], [enable lock checking]),
[ case "$enableval" in
no) enable_lock_check=no ;;
*) enable_lock_check=yes ;;
@@ -167,16 +175,15 @@ AC_ARG_ENABLE(lock-checking,
enable_lock_check=no)
AC_ARG_ENABLE(lock-counter,
-[ --enable-lock-counter enable lock counters
- --disable-lock-counter disable lock counters],
+AS_HELP_STRING([--enable-lock-counter], [enable lock counters]),
[ case "$enableval" in
no) enable_lock_count=no ;;
*) enable_lock_count=yes ;;
esac ], enable_lock_count=no)
AC_ARG_ENABLE(kernel-poll,
-[ --enable-kernel-poll enable kernel poll support
- --disable-kernel-poll disable kernel poll support],
+AS_HELP_STRING([--enable-kernel-poll], [enable kernel poll support])
+AS_HELP_STRING([--disable-kernel-poll], [disable kernel poll support]),
[ case "$enableval" in
no) enable_kernel_poll=no ;;
*) enable_kernel_poll=yes ;;
@@ -184,28 +191,27 @@ AC_ARG_ENABLE(kernel-poll,
AC_ARG_ENABLE(sctp,
-[ --enable-sctp enable sctp support
- --disable-sctp disable sctp support],
+AS_HELP_STRING([--enable-sctp], [enable sctp support])
+AS_HELP_STRING([--disable-sctp], [disable sctp support]),
[ case "$enableval" in
no) enable_sctp=no ;;
*) enable_sctp=yes ;;
esac ], enable_sctp=unknown)
AC_ARG_ENABLE(hipe,
-[ --enable-hipe enable hipe support
- --disable-hipe disable hipe support])
+AS_HELP_STRING([--enable-hipe], [enable hipe support])
+AS_HELP_STRING([--disable-hipe], [disable hipe support]))
AC_ARG_ENABLE(native-libs,
-[ --enable-native-libs compile Erlang libraries to native code])
+AS_HELP_STRING([--enable-native-libs],
+ [compile Erlang libraries to native code]))
AC_ARG_ENABLE(tsp,
-[ --enable-tsp compile tsp app])
-
-AC_ARG_ENABLE(elib-malloc,
-[ --enable-elib-malloc use elib_malloc instead of normal malloc])
+AS_HELP_STRING([--enable-tsp], [compile tsp app]))
AC_ARG_ENABLE(fp-exceptions,
-[ --enable-fp-exceptions Use hardware floating point exceptions (default if hipe enabled)],
+AS_HELP_STRING([--enable-fp-exceptions],
+ [use hardware floating point exceptions (default if hipe enabled)]),
[ case "$enableval" in
no) enable_fp_exceptions=no ;;
*) enable_fp_exceptions=yes ;;
@@ -213,7 +219,8 @@ AC_ARG_ENABLE(fp-exceptions,
],enable_fp_exceptions=auto)
AC_ARG_ENABLE(darwin-universal,
-[ --enable-darwin-universal build universal binaries on darwin i386],
+AS_HELP_STRING([--enable-darwin-universal],
+ [build universal binaries on darwin i386]),
[ case "$enableval" in
no) enable_darwin_universal=no ;;
*) enable_darwin_univeral=yes ;;
@@ -222,7 +229,7 @@ AC_ARG_ENABLE(darwin-universal,
AC_ARG_ENABLE(darwin-64bit,
-[ --enable-darwin-64bit build 64bit binaries on darwin],
+AS_HELP_STRING([--enable-darwin-64bit], [build 64bit binaries on darwin]),
[ case "$enableval" in
no) enable_darwin_64bit=no ;;
*) enable_darwin_64bit=yes ;;
@@ -230,7 +237,8 @@ AC_ARG_ENABLE(darwin-64bit,
],enable_darwin_64bit=no)
AC_ARG_ENABLE(m64-build,
-[ --enable-m64-build build 64bit binaries using the -m64 flag to (g)cc],
+AS_HELP_STRING([--enable-m64-build],
+ [build 64bit binaries using the -m64 flag to (g)cc]),
[ case "$enableval" in
no) enable_m64_build=no ;;
*) enable_m64_build=yes ;;
@@ -238,7 +246,8 @@ AC_ARG_ENABLE(m64-build,
],enable_m64_build=no)
AC_ARG_ENABLE(m32-build,
-[ --enable-m32-build build 32bit binaries using the -m32 flag to (g)cc],
+AS_HELP_STRING([--enable-m32-build],
+ [build 32bit binaries using the -m32 flag to (g)cc]),
[ case "$enableval" in
no) enable_m32_build=no ;;
*)
@@ -251,7 +260,7 @@ AC_ARG_ENABLE(m32-build,
],enable_m32_build=no)
AC_ARG_ENABLE(fixalloc,
-[ --disable-fixalloc disable the use of fix_alloc])
+AS_HELP_STRING([--disable-fixalloc], [disable the use of fix_alloc]))
if test x${enable_fixalloc} = xno ; then
AC_DEFINE(NO_FIX_ALLOC,[],
[Define if you don't want the fix allocator in Erlang])
@@ -259,8 +268,9 @@ fi
AC_SUBST(PERFCTR_PATH)
AC_ARG_WITH(perfctr,
-[ --with-perfctr=PATH specify location of perfctr include and lib
- --without-perfctr don't use perfctr (default)])
+AS_HELP_STRING([--with-perfctr=PATH],
+ [specify location of perfctr include and lib])
+AS_HELP_STRING([--without-perfctr], [don't use perfctr (default)]))
if test "x$with_perfctr" = "xno" -o "x$with_perfctr" = "x" ; then
PERFCTR_PATH=
@@ -274,7 +284,8 @@ else
fi
AC_ARG_ENABLE(clock-gettime,
-[ --enable-clock-gettime Use clock-gettime for time correction],
+AS_HELP_STRING([--enable-clock-gettime],
+ [use clock-gettime for time correction]),
[ case "$enableval" in
no) clock_gettime_correction=no ;;
*) clock_gettime_correction=yes ;;
@@ -1174,17 +1185,15 @@ else
enable_child_waiter_thread=yes
;;
linux*)
- AC_DEFINE(USE_RECURSIVE_MALLOC_MUTEX,[1],
- [Define if malloc should use a recursive mutex])
AC_MSG_CHECKING([whether dlopen() needs to be called before first call to dlerror()])
- if test "x$ETHR_THR_LIB_BASE_NAME" != "xnptl"; then
+ if test "x$ETHR_THR_LIB_BASE_TYPE" != "xposix_nptl"; then
AC_DEFINE(ERTS_NEED_DLOPEN_BEFORE_DLERROR,[1],
[Define if dlopen() needs to be called before first call to dlerror()])
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
fi
- if test "x$ETHR_THR_LIB_BASE_NAME" != "xnptl"; then
+ if test "x$ETHR_THR_LIB_BASE_TYPE" != "xposix_nptl"; then
# Child waiter thread cannot be enabled
disable_child_waiter_thread=yes
enable_child_waiter_thread=no
@@ -1291,8 +1300,7 @@ dnl zlib
dnl -------------
AC_ARG_ENABLE(shared-zlib,
-[ --enable-shared-zlib enable using shared zlib library
- --disable-shared-zlib disable shared zlib, compile own zlib source (default)],
+AS_HELP_STRING([--enable-shared-zlib], [enable using shared zlib library]),
[ case "$enableval" in
no) enable_shared_zlib=no ;;
*) enable_shared_zlib=yes ;;
@@ -1717,6 +1725,9 @@ AC_CHECK_FUNCS([ieee_handler fpsetmask finite isnan isinf res_gethostbyname dlop
gethrtime localtime_r gmtime_r mmap mremap memcpy mallopt \
sbrk _sbrk __sbrk brk _brk __brk \
flockfile fstat strlcpy strlcat setsid posix2time setlocale nl_langinfo poll])
+
+AC_CHECK_DECLS([posix2time],,,[#include <time.h>])
+
if test "X$host" = "Xwin32"; then
ac_cv_func_setvbuf_reversed=yes
fi
@@ -1783,6 +1794,9 @@ AC_CHECK_FUNCS([fdatasync])
dnl Find which C libraries are required to use fdatasync
AC_SEARCH_LIBS(fdatasync, [rt])
+AC_CHECK_HEADERS(net/if_dl.h ifaddrs.h netpacket/packet.h)
+AC_CHECK_FUNCS([getifaddrs])
+
dnl ----------------------------------------------------------------------
dnl Checks for features/quirks in the system that affects Erlang.
dnl ----------------------------------------------------------------------
@@ -1844,6 +1858,27 @@ if test $processor_bind_functionality = yes; then
AC_DEFINE(HAVE_PROCESSOR_BIND, 1, [Define if you have processor_bind functionality])
fi
+AC_MSG_CHECKING([for cpuset_getaffinity/cpuset_setaffinity])
+AC_TRY_COMPILE([
+#include <sys/param.h>
+#include <sys/cpuset.h>
+],
+[
+ int res;
+ cpuset_t cpuset;
+ CPU_ZERO(&cpuset);
+ CPU_SET(1, &cpuset);
+ res = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(cpuset_t), &cpuset);
+ res = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(cpuset_t), &cpuset);
+ res = CPU_ISSET(1, &cpuset);
+ CPU_CLR(1, &cpuset);
+],
+ cpuset_xetaffinity=yes,
+ cpuset_xetaffinity=no)
+AC_MSG_RESULT([$cpuset_xetaffinity])
+if test $cpuset_xetaffinity = yes; then
+ AC_DEFINE(HAVE_CPUSET_xETAFFINITY, 1, [Define if you have cpuset_getaffinity/cpuset_setaffinity])
+fi
AC_CACHE_CHECK([for 'end' symbol],
erts_cv_have_end_symbol,
@@ -2668,7 +2703,7 @@ static __inline__ int check_fpe(double f)
* Implement SIGFPE handler based on CPU/OS combination
*/
-#if (defined(__linux__) && (defined(__i386__) || defined(__x86_64__) || defined(__sparc__) || defined(__powerpc__))) || (defined(__DARWIN__) && (defined(__i386__) || defined(__x86_64__) || defined(__ppc__))) || (defined(__FreeBSD__) && (defined(__i386__) || defined(__x86_64__))) || (defined(__OpenBSD__) && defined(__x86_64__)) || (defined(__sun__) && defined(__x86_64__))
+#if (defined(__linux__) && (defined(__i386__) || defined(__x86_64__) || defined(__sparc__) || defined(__powerpc__))) || (defined(__DARWIN__) && (defined(__i386__) || defined(__x86_64__) || defined(__ppc__))) || (defined(__FreeBSD__) && (defined(__i386__) || defined(__x86_64__))) || ((defined(__OpenBSD__) || defined(__NetBSD__)) && defined(__x86_64__)) || (defined(__sun__) && defined(__x86_64__))
#if defined(__linux__) && defined(__i386__)
#if !defined(X86_FXSR_MAGIC)
@@ -2782,6 +2817,11 @@ static void fpe_sig_action(int sig, siginfo_t *si, void *puc)
struct fxsave64 *fxsave = uc->sc_fpstate;
fxsave->fx_mxcsr = 0x1F80;
fxsave->fx_fsw &= ~0xFF;
+#elif defined(__NetBSD__) && defined(__x86_64__)
+ mcontext_t *mc = &uc->uc_mcontext;
+ struct fxsave64 *fxsave = (struct fxsave64 *)&mc->__fpregs;
+ fxsave->fx_mxcsr = 0x1F80;
+ fxsave->fx_fsw &= ~0xFF;
#elif defined(__sun__) && defined(__x86_64__)
mcontext_t *mc = &uc->uc_mcontext;
struct fpchip_state *fpstate = &mc->fpregs.fp_reg_set.fpchip_state;
@@ -2999,17 +3039,6 @@ if test "x$HIPE_ENABLED" = "xyes" ; then
fi
#
-# Check if we should use elib_malloc.
-#
-
-if test X${enable_elib_malloc} = Xyes; then
- AC_DEFINE(ENABLE_ELIB_MALLOC,[],[Define to enable use of elib_malloc (a malloc() replacement)])
- AC_DEFINE(ELIB_HEAP_SBRK,[],[Elib sbrk])
- AC_DEFINE(ELIB_ALLOC_IS_CLIB,[],[Use elib malloc as clib])
- AC_DEFINE(ELIB_SORTED_BLOCKS,[],[Define to enable the use of sorted blocks when using elib_malloc])
-fi
-
-#
# Check for working poll().
#
AC_MSG_CHECKING([for working poll()])
@@ -3425,14 +3454,16 @@ AC_SUBST(SSL_LINK_WITH_KERBEROS)
AC_SUBST(STATIC_KERBEROS_LIBS)
AC_SUBST(SSL_LINK_WITH_ZLIB)
AC_SUBST(STATIC_ZLIB_LIBS)
-AC_SUBST(OPENSSL_CMD)
std_ssl_locations="/usr/local /usr/sfw /opt/local /usr /usr/pkg /usr/local/openssl /usr/lib/openssl /usr/openssl /usr/local/ssl /usr/lib/ssl /usr/ssl"
AC_ARG_WITH(ssl-zlib,
-[ --with-ssl-zlib=PATH specify location of ZLib to be used by OpenSSL
- --with-ssl-zlib link SSL with Zlib (default if found)
- --without-ssl-zlib don't link SSL with ZLib])
+AS_HELP_STRING([--with-ssl-zlib=PATH],
+ [specify location of ZLib to be used by OpenSSL])
+AS_HELP_STRING([--with-ssl-zlib],
+ [link SSL with Zlib (default if found)])
+AS_HELP_STRING([--without-ssl-zlib],
+ [don't link SSL with ZLib]))
if test "x$with_ssl_zlib" = "xno"; then
@@ -3501,13 +3532,13 @@ fi
AC_ARG_WITH(ssl,
-[ --with-ssl=PATH specify location of OpenSSL include and lib
- --with-ssl use SSL (default)
- --without-ssl don't use SSL])
+AS_HELP_STRING([--with-ssl=PATH], [specify location of OpenSSL include and lib])
+AS_HELP_STRING([--with-ssl], [use SSL (default)])
+AS_HELP_STRING([--without-ssl], [don't use SSL]))
AC_ARG_ENABLE(dynamic-ssl-lib,
-[ --enable-dynamic-ssl-lib enable using dynamic openssl libraries
- --disable-dynamic-ssl-lib disable using dynamic openssl libraries],
+AS_HELP_STRING([--disable-dynamic-ssl-lib],
+ [disable using dynamic openssl libraries]),
[ case "$enableval" in
no) enable_dynamic_ssl=no ;;
*) enable_dynamic_ssl=yes ;;
@@ -3617,21 +3648,6 @@ case "$erl_xcomp_without_sysroot-$with_ssl" in
SSL_DYNAMIC_ONLY=yes
fi
SSL_BINDIR="$rdir/bin"
-dnl Should one use EXEEXT or ac_exeext?
- if test -f "$erl_xcomp_sysroot$SSL_BINDIR/openssl$EXEEXT"; then
- if test "$cross_compiling" = "yes"; then
- dnl Cannot test it; hope it is working...
- OPENSSL_CMD="$SSL_BINDIR/openssl"
- else
- if "$SSL_BINDIR/openssl" version > /dev/null 2>&1; then
- OPENSSL_CMD="$SSL_BINDIR/openssl"
- else
- is_real_ssl=no
- fi
- fi
- else
- is_real_ssl=no
- fi
if test "x$is_real_ssl" = "xyes" ; then
SSL_INCLUDE="-I$dir/include"
old_CPPFLAGS=$CPPFLAGS
@@ -3695,7 +3711,6 @@ dnl Should one use EXEEXT or ac_exeext?
SSL_RUNTIME_LIB="/usr/lib"
SSL_LIB="$erl_xcomp_sysroot/usr/lib"
SSL_BINDIR="/usr/sbin"
- OPENSSL_CMD="$SSL_BINDIR/openssl"
dnl OpenBSD requires us to link with -L and -l
SSL_DYNAMIC_ONLY="yes"
fi
@@ -3781,7 +3796,6 @@ dnl so it is - be adoptable
SSL_DYNAMIC_ONLY=yes
fi
SSL_INCLUDE="-I$with_ssl/include"
- OPENSSL_CMD="$with_ssl/bin/openssl"
SSL_APP=ssl
CRYPTO_APP=crypto
SSH_APP=ssh
@@ -3987,9 +4001,9 @@ esac
AC_ARG_WITH(javac,
-[ --with-javac=JAVAC specify Java compiler to use
- --with-javac use a Java compiler if found (default)
- --without-javac don't use any Java compiler])
+AS_HELP_STRING([--with-javac=JAVAC], [specify Java compiler to use])
+AS_HELP_STRING([--with-javac], [use a Java compiler if found (default)])
+AS_HELP_STRING([--without-javac], [don't use any Java compiler]))
dnl
dnl Then there are a number of apps which needs a java compiler...
@@ -4178,7 +4192,6 @@ dnl
../lib/ic/c_src/$host/Makefile:../lib/ic/c_src/Makefile.in
../lib/os_mon/c_src/$host/Makefile:../lib/os_mon/c_src/Makefile.in
../lib/ssl/c_src/$host/Makefile:../lib/ssl/c_src/Makefile.in
- ../lib/ssl/examples/certs/$host/Makefile:../lib/ssl/examples/certs/Makefile.in
../lib/crypto/c_src/$host/Makefile:../lib/crypto/c_src/Makefile.in
../lib/orber/c_src/$host/Makefile:../lib/orber/c_src/Makefile.in
../lib/runtime_tools/c_src/$host/Makefile:../lib/runtime_tools/c_src/Makefile.in
diff --git a/erts/doc/src/driver.xml b/erts/doc/src/driver.xml
index 006a6160de..db455312ec 100644
--- a/erts/doc/src/driver.xml
+++ b/erts/doc/src/driver.xml
@@ -196,11 +196,14 @@ static ErlDrvData start(ErlDrvPort port, char *command)
<p>We call disconnect to log out from the database.
(This should have been done from Erlang, but just in case.)</p>
<code type="none"><![CDATA[
- static int do_disconnect(our_data_t* data, ei_x_buff* x);
+static int do_disconnect(our_data_t* data, ei_x_buff* x);
static void stop(ErlDrvData drv_data)
{
- do_disconnect((our_data_t*)drv_data, NULL);
+ our_data_t* data = (our_data_t*)drv_data;
+
+ do_disconnect(data, NULL);
+ driver_free(data);
}
]]></code>
<p>We use the binary format only to return data to the emulator;
diff --git a/erts/doc/src/driver_entry.xml b/erts/doc/src/driver_entry.xml
index e71b48bd92..dd949d4048 100644
--- a/erts/doc/src/driver_entry.xml
+++ b/erts/doc/src/driver_entry.xml
@@ -172,7 +172,7 @@ typedef struct erl_drv_entry {
added to the driver list.) The driver should return 0, or if
the driver can't initialize, -1.</p>
</item>
- <tag><marker id="start"/>int (*start)(ErlDrvPort port, char* command)</tag>
+ <tag><marker id="start"/>ErlDrvData (*start)(ErlDrvPort port, char* command)</tag>
<item>
<p>This is called when the driver is instantiated, when
<c>open_port/2</c> is called. The driver should return a
@@ -188,7 +188,9 @@ typedef struct erl_drv_entry {
<p>This is called when the port is closed, with
<c>port_close/1</c> or <c>Port ! {self(), close}</c>. Note
that terminating the port owner process also closes the
- port.</p>
+ port. If <c>drv_data</c> is a pointer to memory allocated in
+ <c>start</c>, then <c>stop</c> is the place to deallocate that
+ memory.</p>
</item>
<tag><marker id="output"/>void (*output)(ErlDrvData drv_data, char *buf, int len)</tag>
<item>
diff --git a/erts/doc/src/epmd.xml b/erts/doc/src/epmd.xml
index 796ab3820b..f01cf90a36 100644
--- a/erts/doc/src/epmd.xml
+++ b/erts/doc/src/epmd.xml
@@ -4,7 +4,7 @@
<comref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2010</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,9 +31,23 @@
<rev>A</rev>
<file>epmd.xml</file>
</header>
+
<com>epmd</com>
- <comsummary>Erlang Port Mapper Daemon </comsummary>
+ <comsummary>
+ <p>Erlang Port Mapper Daemon</p>
+ <taglist>
+ <tag><c><![CDATA[epmd [-d|-debug] [DbgExtra...] [-port No] [-daemon] [-relaxed_command_check]]]></c></tag>
+ <item>
+ <p>Starts the port mapper daemon</p>
+ </item>
+ <tag><c><![CDATA[epmd [-d|-debug] [-port No] [-names|-kill|-stop Name]]]></c></tag>
+ <item>
+ <p>Communicates with a running port mapper daemon</p>
+ </item>
+ </taglist>
+ </comsummary>
<description>
+
<p>This daemon acts as a name server on all hosts involved in
distributed Erlang computations. When an Erlang node
starts, the node has a name and it obtains an address from the host
@@ -46,48 +60,171 @@
The job of the <c><![CDATA[epmd]]></c> daemon is to keep track of which
node name listens on which address. Hence, <c><![CDATA[epmd]]></c> map
symbolic node names to machine addresses.</p>
- <p>The daemon is started automatically by the Erlang start-up script.</p>
- <p>The program <c><![CDATA[epmd]]></c> can also be used for a variety of other
- purposes, for example checking the DNS (Domain Name System)
- configuration of a host.</p>
+
+ <p>The TCP/IP <c>epmd</c> daemon actually only keeps track of
+ the <c>Name</c> (first) part of an Erlang node name, the <c>Host</c>
+ part (whatever is after the <c><![CDATA[@]]></c> is implicit in the
+ node name where the <c>epmd</c> daemon was actually contacted,
+ as is the IP address where the Erlang node can be
+ reached. Consistent and correct TCP naming services are
+ therefore required for an Erlang network to function
+ correctly.</p>
+
+ <taglist>
+ <tag>Starting the port mapper daemon</tag>
+ <item>
+
+ <p>The daemon is started automatically by the <c>erl</c>
+ command if the node is to be distributed and there is no
+ running instance present. If automatically launched,
+ environment variables has to be used to alter the behavior of
+ the daemon. See the <seealso
+ marker="#environment_variables">Environment
+ variables</seealso> section below.</p>
+
+ <p>If the -daemon argument is not given, the
+ <c><![CDATA[epmd]]></c> runs as a normal program with the
+ controlling terminal of the shell in which it is
+ started. Normally, it should run as a daemon.</p>
+
+ <p>Regular start-up options are described in the
+ <seealso marker="#daemon_flags">Regular options</seealso>
+ section below.</p>
+
+ <p>The <c>DbgExtra</c> options are described in the
+ <seealso marker="#debug_flags">DbgExtra options</seealso>
+ section below.</p>
+
+ </item>
+ <tag>Communicating with a running port mapper daemon</tag>
+ <item>
+
+ <p>Communicating with the running epmd daemon by means of the
+ <c>epmd</c> program is done primarily for debugging
+ purposes.</p>
+
+ <p>The different queries are described in the <seealso
+ marker="#interactive_flags">Interactive options</seealso>
+ section below.</p>
+
+ </item>
+ </taglist>
</description>
- <funcs>
- <func>
- <name>epmd [-daemon] </name>
- <fsummary>Start a name server as a daemon</fsummary>
- <desc>
- <p>Starts a name server as a daemon. If it has no argument, the
- <c><![CDATA[epmd]]></c> runs as a normal program with the controlling terminal
- of the shell in which it is started. Normally, it should run as a
- daemon.</p>
- </desc>
- </func>
- <func>
- <name>epmd -names</name>
- <fsummary>Request the names of the registered Erlang nodes on this host</fsummary>
- <desc>
- <p>Requests the names of the local Erlang nodes <c><![CDATA[epmd]]></c> has
- registered.</p>
- </desc>
- </func>
- <func>
- <name>epmd -kill</name>
- <fsummary>Kill the <c><![CDATA[epmd]]></c>process</fsummary>
- <desc>
- <p>Kills the <c><![CDATA[epmd]]></c> process.</p>
- </desc>
- </func>
- <func>
- <name>epmd -help</name>
- <fsummary>List options</fsummary>
- <desc>
- <p>Write short info about the usage including some debugging
- options not listed here.</p>
- </desc>
- </func>
- </funcs>
+ <section>
+ <marker id="daemon_flags"></marker>
+ <title>Regular options</title>
+
+ <p>These options are available when starting the actual name server. The name server is normally started automatically by the <c>erl</c> command (if not already available), but it can also be started at i.e. system start-up.</p>
+ <taglist>
+ <tag><c><![CDATA[-port No]]></c></tag>
+ <item>
+ <p>Let this instance of epmd listen to another TCP port than
+ default 4369. This can be also be set using the
+ <c><![CDATA[ERL_EPMD_PORT]]></c> environment variable, see the
+ section <seealso marker="#environment_variables">Environment
+ variables</seealso> below</p>
+ </item>
+ <tag><c><![CDATA[-d | -debug]]></c></tag>
+ <item>
+
+ <p>Enable debug output. The more <c>-d</c> flags given, the more
+ debug output you will get (to a certain limit). This option is
+ most useful when the epmd daemon is not started as a daemon.</p>
+ </item>
+ <tag><c><![CDATA[-daemon]]></c></tag>
+ <item>
+ <p>Start epmd detached from the controlling terminal. Logging will end up in syslog when available and correctly configured. If the epmd daemon is started at boot, this option should definitely be used. It is also used when the <c>erl</c> command automatically starts <c>epmd</c>.</p>
+ </item>
+ <tag><c><![CDATA[-relaxed_command_check]]></c></tag>
+ <item>
+ <p>Start the epmd program with relaxed command checking (mostly for backward compatibility). This affects the following:</p>
+ <list type="bulleted">
+ <item>
+ <p>With relaxed command checking, the <c>epmd</c> daemon can be killed from the localhost with i.e. <c>epmd -kill</c> even if there are active nodes registered. Normally only daemons with an empty node database can be killed with the <c>epmd -kill</c> command.</p>
+ </item>
+ <item>
+ <p>The <c>epmd -stop</c> command (and the corresponding messages to epmd, as can be given using <c>erl_interface/ei</c>) is normally always ignored, as it opens up for strange situation when two nodes of the same name can be alive at the same time. A node unregisters itself by just closing the connection to epmd, why the <c>stop</c> command was only intended for use in debugging situations.</p>
+ <p>With relaxed command checking enabled, you can forcibly unregister live nodes.</p>
+ </item>
+ </list>
+ <p>Relaxed command checking can also be enabled by setting the environment variable <c>ERL_EPMD_RELAXED_COMMAND_CHECK</c> prior to starting <c>epmd</c>.</p>
+ <p>Only use relaxed command checking on systems with very limited interactive usage.</p>
+ </item>
+ </taglist>
+ </section>
<section>
+ <marker id="debug_flags"></marker>
+ <title>DbgExtra options</title>
+ <p>These options are purely for debugging and testing epmd clients, they should not be used in normal operation.</p>
+
+ <taglist>
+ <tag><c><![CDATA[-packet_timeout Seconds]]></c></tag>
+ <item>
+ <p>Set the number of seconds a connection can be
+ inactive before epmd times out and closes the
+ connection (default 60).</p>
+ </item>
+ <tag><c><![CDATA[-delay_accept Seconds]]></c></tag>
+ <item>
+ <p>To simulate a busy server you can insert a delay between epmd
+ gets notified about that a new connection is requested and
+ when the connections gets accepted.</p>
+ </item>
+ <tag><c><![CDATA[-delay_write Seconds]]></c></tag>
+ <item>
+ <p>Also a simulation of a busy server. Inserts
+ a delay before a reply is sent.</p>
+ </item>
+ </taglist>
+ </section>
+ <section>
+ <marker id="interactive_flags"></marker>
+ <title>Interactive options</title>
+ <p>These options make <c>epmd</c> run as an interactive command displaying the results of sending queries ta an already running instance of <c>epmd</c>. The epmd contacted is always on the local node, but the <c>-port</c> option can be used to select between instances if several are running using different port on the host.</p>
+ <taglist>
+ <tag><c><![CDATA[-port No]]></c></tag>
+ <item>
+ <p>Contacts the <c>epmd</c> listening on the given TCP port number
+ (default 4369). This can be also be set using the
+ <c><![CDATA[ERL_EPMD_PORT]]></c> environment variable, see the
+ section <seealso marker="#environment_variables">Environment
+ variables</seealso> below</p>
+ </item>
+ <tag><c><![CDATA[-names]]></c></tag>
+ <item>
+ <p>List names registered with the currently running epmd</p>
+ </item>
+ <tag><c><![CDATA[-kill]]></c></tag>
+ <item>
+ <p>Kill the currently running <c>epmd</c>.</p>
+
+ <p>Killing the running <c>epmd</c> is only allowed if <c>epmd
+ -names</c> show an empty database or
+ <c>-relaxed_command_check</c> was given when the running
+ instance of <c>epmd</c> was started. Note that
+ <c>-relaxed_command_check</c> is given when starting the
+ daemon that is to accept killing when it has live nodes
+ registered. When running epmd interactively,
+ <c>-relaxed_command_check</c> has no effect. A daemon that is
+ started without relaxed command checking has to be killed
+ using i.e. signals or some other OS specific method if it has
+ active clients registered.</p>
+ </item>
+ <tag><c><![CDATA[-stop Name]]></c></tag>
+ <item>
+ <p>Forcibly unregister a live node from <c>epmd</c>'s database</p>
+
+ <p>This command can only be used when contacting <c>epmd</c>
+ instances started with the <c>-relaxed_command_check</c>
+ flag. Note that relaxed command checking has to be enabled for
+ the <c>epmd</c> daemon contacted, When running epmd
+ interactively,
+ <c>-relaxed_command_check</c> has no effect.</p>
+ </item>
+ </taglist>
+ </section>
+ <section>
<marker id="environment_variables"></marker>
<title>Environment variables</title>
<taglist>
@@ -99,6 +236,15 @@
independent clusters of nodes, to co-exist on the same host.
All nodes in a cluster must use the same epmd port number.</p>
</item>
+ <tag><c><![CDATA[ERL_EPMD_RELAXED_COMMAND_CHECK]]></c></tag>
+ <item>
+ <p>If set prior to start, the <c>epmd</c> daemon will behave
+ as if the <c>-relaxed_command_check</c> option was given at
+ start-up. If consequently setting this option before starting
+ the Erlang virtual machine, the automatically started
+ <c>epmd</c> will accept the <c>-kill</c> and <c>-stop</c>
+ commands without restrictions.</p>
+ </item>
</taglist>
</section>
@@ -116,5 +262,29 @@
silently be ignored.
</p>
</section>
+ <section>
+ <title>Access restrictions</title>
+ <p>The <c>epmd</c> daemon accepts messages from both localhost and
+ remote hosts. However, only the query commands are answered (and
+ acted upon) if the query comes from a remote host. It is always an
+ error to try to register a nodename if the client is not a process
+ located on the same host as the <c>epmd</c> instance is running on,
+ why such requests are considered hostile and the connection is
+ immediately closed.</p>
+
+ <p>The queries accepted from remote nodes are:</p>
+ <list type="bulleted">
+ <item>
+ <p>Port queries - i.e. on which port does the node with a given
+ name listen</p>
+ </item>
+ <item>
+ <p>Name listing - i.e. give a list of all names registered on
+ the host</p>
+ </item>
+ </list>
+ <p>To restrict access further, firewall software has to be used.</p>
+ </section>
+
</comref>
diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml
index 0e26d62548..a1d73fb698 100644
--- a/erts/doc/src/erl.xml
+++ b/erts/doc/src/erl.xml
@@ -685,8 +685,8 @@
<seealso marker="erlang#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type, default_bind)</seealso>.
</p></item>
</taglist>
- <p>Binding of schedulers are currently only supported on newer
- Linux and Solaris systems.</p>
+ <p>Binding of schedulers is currently only supported on newer
+ Linux, Solaris, FreeBSD, and Windows systems.</p>
<p>If no CPU topology is available when the <c>+sbt</c> flag
is processed and <c>BindType</c> is any other type than
<c>u</c>, the runtime system will fail to start. CPU
@@ -831,14 +831,28 @@
<p>For more information, see
<seealso marker="erlang#system_flag_cpu_topology">erlang:system_flag(cpu_topology, CpuTopology)</seealso>.</p>
</item>
+ <tag><marker id="+swt"><c>+swt very_low|low|medium|high|very_high</c></marker></tag>
+ <item>
+ <p>Set scheduler wakeup threshold. Default is <c>medium</c>.
+ The threshold determines when to wake up sleeping schedulers
+ when more work than can be handled by currently awake schedulers
+ exist. A low threshold will cause earlier wakeups, and a high
+ threshold will cause later wakeups. Early wakeups will
+ distribute work over multiple schedulers faster, but work will
+ more easily bounce between schedulers.
+ </p>
+ <p><em>NOTE:</em> This flag may be removed or changed at any time
+ without prior notice.
+ </p>
+ </item>
+ <tag><marker id="sched_thread_stack_size"><c><![CDATA[+sss size]]></c></marker></tag>
+ <item>
+ <p>Suggested stack size, in kilowords, for scheduler threads.
+ Valid range is 4-8192 kilowords. The default stack size
+ is OS dependent.</p>
+ </item>
</taglist>
</item>
- <tag><marker id="sched_thread_stack_size"><c><![CDATA[+sss size]]></c></marker></tag>
- <item>
- <p>Suggested stack size, in kilowords, for scheduler threads.
- Valid range is 4-8192 kilowords. The default stack size
- is OS dependent.</p>
- </item>
<tag><marker id="+t"><c><![CDATA[+t size]]></c></marker></tag>
<item>
<p>Set the maximum number of atoms the VM can handle. Default is 1048576.</p>
@@ -892,6 +906,25 @@
<seealso marker="kernel:error_logger#warning_map/0">error_logger(3)</seealso>
for further information.</p>
</item>
+ <tag><c><![CDATA[+zFlag Value]]></c></tag>
+ <item>
+ <p>Miscellaneous flags.</p>
+ <taglist>
+ <tag><marker id="+zdbbl"><c>+zdbbl size</c></marker></tag>
+ <item>
+ <p>Set the distribution buffer busy limit
+ (<seealso marker="erlang#system_info_dist_buf_busy_limit">dist_buf_busy_limit</seealso>)
+ in kilobytes. Valid range is 1-2097151. Default is 1024.</p>
+ <p>A larger buffer limit will allow processes to buffer
+ more outgoing messages over the distribution. When the
+ buffer limit has been reached, sending processes will be
+ suspended until the buffer size has shrunk. The buffer
+ limit is per distribution channel. A higher limit will
+ give lower latency and higher throughput at the expense
+ of higher memory usage.</p>
+ </item>
+ </taglist>
+ </item>
</taglist>
</section>
diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml
index f7b7b2f346..27887cbdf6 100644
--- a/erts/doc/src/erl_nif.xml
+++ b/erts/doc/src/erl_nif.xml
@@ -4,7 +4,7 @@
<cref>
<header>
<copyright>
- <year>2001</year><year>2009</year>
+ <year>2001</year><year>2010</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -34,11 +34,10 @@
<lib>erl_nif</lib>
<libsummary>API functions for an Erlang NIF library</libsummary>
<description>
- <warning><p>The NIF concept was introduced in R13B03 as an
- EXPERIMENTAL feature. The interfaces may be changed in any way
- in coming releases. The plan is however to lift the experimental label and
- maintain interface backward compatibility from R14B.</p>
- <p>Incompatible changes in <em>R14A</em>:</p>
+ <note><p>The NIF concept is officially supported from R14B. NIF source code
+ written for earlier experimental versions might need adaption to run on R14B.</p>
+ <p>No incompatible changes between <em>R14B</em> and R14A.</p>
+ <p>Incompatible changes between <em>R14A</em> and R13B04:</p>
<list>
<item>Environment argument removed for <c>enif_alloc</c>,
<c>enif_realloc</c>, <c>enif_free</c>, <c>enif_alloc_binary</c>,
@@ -50,14 +49,14 @@
<item>Module argument added to <c>enif_open_resource_type</c>
while changing name spaces of resource types from global to module local.</item>
</list>
- <p>Incompatible changes in <em>R13B04</em>:</p>
+ <p>Incompatible changes between <em>R13B04</em> and R13B03:</p>
<list>
<item>The function prototypes of the NIFs have changed to expect <c>argc</c> and <c>argv</c>
arguments. The arity of a NIF is by that no longer limited to 3.</item>
<item><c>enif_get_data</c> renamed as <c>enif_priv_data</c>.</item>
<item><c>enif_make_string</c> got a third argument for character encoding.</item>
</list>
- </warning>
+ </note>
<p>A NIF library contains native implementation of some functions
of an Erlang module. The native implemented functions (NIFs) are
@@ -456,6 +455,10 @@ typedef enum {
to return information about the runtime system. Contains currently
the exact same content as <seealso marker="erl_driver#ErlDrvSysInfo">ErlDrvSysInfo</seealso>.</p>
</item>
+ <tag><marker id="ErlNifSInt64"/>ErlNifSInt64</tag>
+ <item><p>A native signed 64-bit integer type.</p></item>
+ <tag><marker id="ErlNifUInt64"/>ErlNifUInt64</tag>
+ <item><p>A native unsigned 64-bit integer type.</p></item>
</taglist>
</section>
@@ -571,7 +574,13 @@ typedef enum {
<fsummary>Read an integer term</fsummary>
<desc><p>Set <c>*ip</c> to the integer value of
<c>term</c>. Return true on success or false if <c>term</c> is not an
- integer or is outside the bounds of type <c>int</c></p></desc>
+ integer or is outside the bounds of type <c>int</c>.</p></desc>
+ </func>
+ <func><name><ret>int</ret><nametext>enif_get_int64(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifSInt64* ip)</nametext></name>
+ <fsummary>Read a 64-bit integer term</fsummary>
+ <desc><p>Set <c>*ip</c> to the integer value of
+ <c>term</c>. Return true on success or false if <c>term</c> is not an
+ integer or is outside the bounds of a signed 64-bit integer.</p></desc>
</func>
<func><name><ret>int</ret><nametext>enif_get_local_pid(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifPid* pid)</nametext></name>
<fsummary>Read an local pid term</fsummary>
@@ -633,7 +642,12 @@ typedef enum {
return true, or return false if <c>term</c> is not an unsigned integer or
is outside the bounds of type <c>unsigned int</c>.</p></desc>
</func>
-
+ <func><name><ret>int</ret><nametext>enif_get_uint64(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifUInt64* ip)</nametext></name>
+ <fsummary>Read an unsigned 64-bit integer term.</fsummary>
+ <desc><p>Set <c>*ip</c> to the unsigned integer value of <c>term</c> and
+ return true, or return false if <c>term</c> is not an unsigned integer or
+ is outside the bounds of an unsigned 64-bit integer.</p></desc>
+ </func>
<func><name><ret>int</ret><nametext>enif_get_ulong(ErlNifEnv* env, ERL_NIF_TERM term, unsigned long* ip)</nametext></name>
<fsummary>Read an unsigned integer term.</fsummary>
<desc><p>Set <c>*ip</c> to the unsigned long integer value of <c>term</c>
@@ -758,6 +772,10 @@ typedef enum {
<fsummary>Create an integer term</fsummary>
<desc><p>Create an integer term.</p></desc>
</func>
+ <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_int64(ErlNifEnv* env, ErlNifSInt64 i)</nametext></name>
+ <fsummary>Create an integer term</fsummary>
+ <desc><p>Create an integer term from a signed 64-bit integer.</p></desc>
+ </func>
<func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list(ErlNifEnv* env, unsigned cnt, ...)</nametext></name>
<fsummary>Create a list term.</fsummary>
<desc><p>Create an ordinary list term of length <c>cnt</c>. Expects
@@ -894,6 +912,10 @@ typedef enum {
<fsummary>Create an unsigned integer term</fsummary>
<desc><p>Create an integer term from an <c>unsigned int</c>.</p></desc>
</func>
+ <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_uint64(ErlNifEnv* env, ErlNifUInt64 i)</nametext></name>
+ <fsummary>Create an unsigned integer term</fsummary>
+ <desc><p>Create an integer term from an unsigned 64-bit integer.</p></desc>
+ </func>
<func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_ulong(ErlNifEnv* env, unsigned long i)</nametext></name>
<fsummary>Create an integer term from an unsigned long int</fsummary>
<desc><p>Create an integer term from an <c>unsigned long int</c>.</p></desc>
@@ -1108,7 +1130,7 @@ typedef enum {
</funcs>
<section>
<title>SEE ALSO</title>
- <p><seealso marker="erlang#load_nif-2">load_nif(3)</seealso></p>
+ <p><seealso marker="erlang#load_nif-2">erlang:load_nif/2</seealso></p>
</section>
</cref>
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index 54a0a80536..638f7eef10 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -80,7 +80,7 @@ iolist() = [char() | binary() | iolist()]
</desc>
</func>
<func>
- <name>adler32(Data) -> int()</name>
+ <name>erlang:adler32(Data) -> int()</name>
<fsummary>Compute adler32 checksum</fsummary>
<type>
<v>Data = iodata()</v>
@@ -90,7 +90,7 @@ iolist() = [char() | binary() | iolist()]
</desc>
</func>
<func>
- <name>adler32(OldAdler, Data) -> int()</name>
+ <name>erlang:adler32(OldAdler, Data) -> int()</name>
<fsummary>Compute adler32 checksum</fsummary>
<type>
<v>OldAdler = int()</v>
@@ -102,17 +102,17 @@ iolist() = [char() | binary() | iolist()]
<c>Data</c>.</p>
<p>The following code:</p>
<code>
- X = adler32(Data1),
- Y = adler32(X,Data2).
+ X = erlang:adler32(Data1),
+ Y = erlang:adler32(X,Data2).
</code>
<p>- would assign the same value to <c>Y</c> as this would:</p>
<code>
- Y = adler32([Data1,Data2]).
+ Y = erlang:adler32([Data1,Data2]).
</code>
</desc>
</func>
<func>
- <name>adler32_combine(FirstAdler, SecondAdler, SecondSize) -> int()</name>
+ <name>erlang:adler32_combine(FirstAdler, SecondAdler, SecondSize) -> int()</name>
<fsummary>Combine two adler32 checksums</fsummary>
<type>
<v>FirstAdler = SecondAdler = int()</v>
@@ -124,14 +124,14 @@ iolist() = [char() | binary() | iolist()]
the second checksum to be known.</p>
<p>The following code:</p>
<code>
- Y = adler32(Data1),
- Z = adler32(Y,Data2).
+ Y = erlang:adler32(Data1),
+ Z = erlang:adler32(Y,Data2).
</code>
<p>- would assign the same value to <c>Z</c> as this would:</p>
<code>
- X = adler32(Data1),
- Y = adler32(Data2),
- Z = adler32_combine(X,Y,iolist_size(Data2)).
+ X = erlang:adler32(Data1),
+ Y = erlang:adler32(Data2),
+ Z = erlang:adler32_combine(X,Y,iolist_size(Data2)).
</code>
</desc>
</func>
@@ -147,7 +147,7 @@ iolist() = [char() | binary() | iolist()]
<c>Tuple1</c>, and contains the elements in <c>Tuple1</c>
followed by <c>Term</c> as the last element. Semantically
equivalent to
- <c>list_to_tuple(tuple_to_list(Tuple ++ [Term])</c>, but much
+ <c>list_to_tuple(tuple_to_list(Tuple) ++ [Term])</c>, but much
faster.</p>
<pre>
> <input>erlang:append_element({one, two}, three).</input>
@@ -499,7 +499,7 @@ iolist() = [char() | binary() | iolist()]
<name>erlang:cancel_timer(TimerRef) -> Time | false</name>
<fsummary>Cancel a timer</fsummary>
<type>
- <v>TimerRef = ref()</v>
+ <v>TimerRef = reference()</v>
<v>Time = int()</v>
</type>
<desc>
@@ -553,7 +553,7 @@ false</pre>
</desc>
</func>
<func>
- <name>crc32(Data) -> int()</name>
+ <name>erlang:crc32(Data) -> int()</name>
<fsummary>Compute crc32 (IEEE 802.3) checksum</fsummary>
<type>
<v>Data = iodata()</v>
@@ -563,7 +563,7 @@ false</pre>
</desc>
</func>
<func>
- <name>crc32(OldCrc, Data) -> int()</name>
+ <name>erlang:crc32(OldCrc, Data) -> int()</name>
<fsummary>Compute crc32 (IEEE 802.3) checksum</fsummary>
<type>
<v>OldCrc = int()</v>
@@ -575,17 +575,17 @@ false</pre>
<c>Data</c>.</p>
<p>The following code:</p>
<code>
- X = crc32(Data1),
- Y = crc32(X,Data2).
+ X = erlang:crc32(Data1),
+ Y = erlang:crc32(X,Data2).
</code>
<p>- would assign the same value to <c>Y</c> as this would:</p>
<code>
- Y = crc32([Data1,Data2]).
+ Y = erlang:crc32([Data1,Data2]).
</code>
</desc>
</func>
<func>
- <name>crc32_combine(FirstCrc, SecondCrc, SecondSize) -> int()</name>
+ <name>erlang:crc32_combine(FirstCrc, SecondCrc, SecondSize) -> int()</name>
<fsummary>Combine two crc32 (IEEE 802.3) checksums</fsummary>
<type>
<v>FirstCrc = SecondCrc = int()</v>
@@ -597,14 +597,14 @@ false</pre>
the second checksum to be known.</p>
<p>The following code:</p>
<code>
- Y = crc32(Data1),
- Z = crc32(Y,Data2).
+ Y = erlang:crc32(Data1),
+ Z = erlang:crc32(Y,Data2).
</code>
<p>- would assign the same value to <c>Z</c> as this would:</p>
<code>
- X = crc32(Data1),
- Y = crc32(Data2),
- Z = crc32_combine(X,Y,iolist_size(Data2)).
+ X = erlang:crc32(Data1),
+ Y = erlang:crc32(Data2),
+ Z = erlang:crc32_combine(X,Y,iolist_size(Data2)).
</code>
</desc>
</func>
@@ -624,7 +624,7 @@ false</pre>
</desc>
</func>
<func>
- <name>decode_packet(Type,Bin,Options) -> {ok,Packet,Rest} | {more,Length} | {error,Reason}</name>
+ <name>erlang:decode_packet(Type,Bin,Options) -> {ok,Packet,Rest} | {more,Length} | {error,Reason}</name>
<fsummary>Extracts a protocol packet from a binary</fsummary>
<type>
<v>Bin = binary()</v>
@@ -760,18 +760,18 @@ false</pre>
</desc>
</func>
<func>
- <name>erlang:demonitor(MonitorRef) -> true</name>
+ <name>demonitor(MonitorRef) -> true</name>
<fsummary>Stop monitoring</fsummary>
<type>
- <v>MonitorRef = ref()</v>
+ <v>MonitorRef = reference()</v>
</type>
<desc>
<p>If <c>MonitorRef</c> is a reference which the calling process
obtained by calling
- <seealso marker="#monitor/2">erlang:monitor/2</seealso>,
+ <seealso marker="#monitor/2">monitor/2</seealso>,
this monitoring is turned off. If the monitoring is already
turned off, nothing happens.</p>
- <p>Once <c>erlang:demonitor(MonitorRef)</c> has returned it is
+ <p>Once <c>demonitor(MonitorRef)</c> has returned it is
guaranteed that no <c>{'DOWN', MonitorRef, _, _, _}</c> message
due to the monitor will be placed in the callers message queue
in the future. A <c>{'DOWN', MonitorRef, _, _, _}</c> message
@@ -779,10 +779,10 @@ false</pre>
the call, though. Therefore, in most cases, it is advisable
to remove such a <c>'DOWN'</c> message from the message queue
after monitoring has been stopped.
- <seealso marker="#demonitor/2">erlang:demonitor(MonitorRef, [flush])</seealso> can be used instead of
- <c>erlang:demonitor(MonitorRef)</c> if this cleanup is wanted.</p>
+ <seealso marker="#demonitor/2">demonitor(MonitorRef, [flush])</seealso> can be used instead of
+ <c>demonitor(MonitorRef)</c> if this cleanup is wanted.</p>
<note>
- <p>Prior to OTP release R11B (erts version 5.5) <c>erlang:demonitor/1</c>
+ <p>Prior to OTP release R11B (erts version 5.5) <c>demonitor/1</c>
behaved completely asynchronous, i.e., the monitor was active
until the "demonitor signal" reached the monitored entity. This
had one undesirable effect, though. You could never know when
@@ -800,10 +800,10 @@ false</pre>
</desc>
</func>
<func>
- <name>erlang:demonitor(MonitorRef, OptionList) -> true|false</name>
+ <name>demonitor(MonitorRef, OptionList) -> true|false</name>
<fsummary>Stop monitoring</fsummary>
<type>
- <v>MonitorRef = ref()</v>
+ <v>MonitorRef = reference()</v>
<v>OptionList = [Option]</v>
<v>Option = flush</v>
<v>Option = info</v>
@@ -812,8 +812,8 @@ false</pre>
<p>The returned value is <c>true</c> unless <c>info</c> is part
of <c>OptionList</c>.
</p>
- <p><c>erlang:demonitor(MonitorRef, [])</c> is equivalent to
- <seealso marker="#demonitor/1">erlang:demonitor(MonitorRef)</seealso>.</p>
+ <p><c>demonitor(MonitorRef, [])</c> is equivalent to
+ <seealso marker="#demonitor/1">demonitor(MonitorRef)</seealso>.</p>
<p>Currently the following <c>Option</c>s are valid:</p>
<taglist>
<tag><c>flush</c></tag>
@@ -821,11 +821,11 @@ false</pre>
<p>Remove (one) <c>{_, MonitorRef, _, _, _}</c> message,
if there is one, from the callers message queue after
monitoring has been stopped.</p>
- <p>Calling <c>erlang:demonitor(MonitorRef, [flush])</c>
+ <p>Calling <c>demonitor(MonitorRef, [flush])</c>
is equivalent to the following, but more efficient:</p>
<code type="none">
- erlang:demonitor(MonitorRef),
+ demonitor(MonitorRef),
receive
{_, MonitorRef, _, _, _} ->
true
@@ -863,7 +863,7 @@ false</pre>
</note>
<p>Failure: <c>badarg</c> if <c>OptionList</c> is not a list, or
if <c>Option</c> is not a valid option, or the same failure as for
- <seealso marker="#demonitor/1">erlang:demonitor/1</seealso></p>
+ <seealso marker="#demonitor/1">demonitor/1</seealso></p>
</desc>
</func>
<func>
@@ -944,7 +944,7 @@ b</pre>
</desc>
</func>
<func>
- <name>erlang:error(Reason)</name>
+ <name>error(Reason)</name>
<fsummary>Stop execution with a given reason</fsummary>
<type>
<v>Reason = term()</v>
@@ -957,7 +957,7 @@ b</pre>
function first). Since evaluating this function causes
the process to terminate, it has no return value.</p>
<pre>
-> <input>catch erlang:error(foobar).</input>
+> <input>catch error(foobar).</input>
{'EXIT',{foobar,[{erl_eval,do_apply,5},
{erl_eval,expr,5},
{shell,exprs,6},
@@ -966,7 +966,7 @@ b</pre>
</desc>
</func>
<func>
- <name>erlang:error(Reason, Args)</name>
+ <name>error(Reason, Args)</name>
<fsummary>Stop execution with a given reason</fsummary>
<type>
<v>Reason = term()</v>
@@ -1483,7 +1483,7 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>erlang:integer_to_list(Integer, Base) -> string()</name>
+ <name>integer_to_list(Integer, Base) -> string()</name>
<fsummary>Text representation of an integer</fsummary>
<type>
<v>Integer = int()</v>
@@ -1493,7 +1493,7 @@ os_prompt%</pre>
<p>Returns a string which corresponds to the text
representation of <c>Integer</c> in base <c>Base</c>.</p>
<pre>
-> <input>erlang:integer_to_list(1023, 16).</input>
+> <input>integer_to_list(1023, 16).</input>
"3FF"</pre>
</desc>
</func>
@@ -1932,7 +1932,7 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>erlang:list_to_integer(String, Base) -> int()</name>
+ <name>list_to_integer(String, Base) -> int()</name>
<fsummary>Convert from text representation to an integer</fsummary>
<type>
<v>String = string()</v>
@@ -1942,7 +1942,7 @@ os_prompt%</pre>
<p>Returns an integer whose text representation in base
<c>Base</c> is <c>String</c>.</p>
<pre>
-> <input>erlang:list_to_integer("3FF", 16).</input>
+> <input>list_to_integer("3FF", 16).</input>
1023</pre>
<p>Failure: <c>badarg</c> if <c>String</c> contains a bad
representation of an integer.</p>
@@ -2034,16 +2034,18 @@ os_prompt%</pre>
<v>Text = string()</v>
</type>
<desc>
- <warning>
- <p>This BIF is still an experimental feature. The interface
- may be changed in any way in future releases.</p><p>In
- R13B03 the return value on failure was
+ <note>
+ <p>In releases older than OTP R14B, NIFs were an
+ experimental feature. Versions of OTP older than R14B might
+ have different and possibly incompatible NIF semantics and
+ interfaces. For example, in R13B03 the return value on
+ failure was
<c>{error,Reason,Text}</c>.</p>
- </warning>
+ </note>
<p>Loads and links a dynamic library containing native
implemented functions (NIFs) for a module. <c>Path</c> is a
file path to the sharable object/dynamic library file minus
- the OS-dependant file extension (.so for Unix and .ddl for
+ the OS-dependent file extension (.so for Unix and .dll for
Windows). See <seealso marker="erl_nif">erl_nif</seealso>
on how to implement a NIF library.</p>
<p><c>LoadInfo</c> can be any term. It will be passed on to
@@ -2160,7 +2162,7 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>make_ref() -> ref()</name>
+ <name>make_ref() -> reference()</name>
<fsummary>Return an almost unique reference</fsummary>
<desc>
<p>Returns an almost unique reference.</p>
@@ -2486,7 +2488,7 @@ os_prompt%</pre>
</desc>
</func>
<func>
- <name>erlang:monitor(Type, Item) -> MonitorRef</name>
+ <name>monitor(Type, Item) -> MonitorRef</name>
<fsummary>Start monitoring</fsummary>
<type>
<v>Type = process</v>
@@ -2522,7 +2524,7 @@ os_prompt%</pre>
<note>
<p>When a process is monitored by registered name, the process
that has the registered name at the time when
- <c>erlang:monitor/2</c> is called will be monitored.
+ <c>monitor/2</c> is called will be monitored.
The monitor will not be effected, if the registered name is
unregistered.</p>
</note>
@@ -2556,20 +2558,20 @@ os_prompt%</pre>
</item>
</taglist>
<note>
- <p>If/when <c>erlang:monitor/2</c> is extended (e.g. to
+ <p>If/when <c>monitor/2</c> is extended (e.g. to
handle other item types than <c>process</c>), other
possible values for <c>Object</c>, and <c>Info</c> in the
<c>'DOWN'</c> message will be introduced.</p>
</note>
<p>The monitoring is turned off either when the <c>'DOWN'</c>
message is sent, or when
- <seealso marker="#demonitor/1">erlang:demonitor/1</seealso>
+ <seealso marker="#demonitor/1">demonitor/1</seealso>
is called.</p>
<p>If an attempt is made to monitor a process on an older node
(where remote process monitoring is not implemented or one
where remote process monitoring by registered name is not
implemented), the call fails with <c>badarg</c>.</p>
- <p>Making several calls to <c>erlang:monitor/2</c> for the same
+ <p>Making several calls to <c>monitor/2</c> for the same
<c>Item</c> is not an error; it results in as many, completely
independent, monitorings.</p>
<note>
@@ -2690,7 +2692,7 @@ os_prompt%</pre>
<name>node(Arg) -> Node</name>
<fsummary>At which node is a pid, port or reference located</fsummary>
<type>
- <v>Arg = pid() | port() | ref()</v>
+ <v>Arg = pid() | port() | reference()</v>
<v>Node = node()</v>
</type>
<desc>
@@ -3897,11 +3899,11 @@ os_prompt%</pre>
<tag><c>{monitored_by, Pids}</c></tag>
<item>
<p>A list of pids that are monitoring the process (with
- <c>erlang:monitor/2</c>).</p>
+ <c>monitor/2</c>).</p>
</item>
<tag><c>{monitors, Monitors}</c></tag>
<item>
- <p>A list of monitors (started by <c>erlang:monitor/2</c>)
+ <p>A list of monitors (started by <c>monitor/2</c>)
that are active for the process. For a local process
monitor or a remote process monitor by pid, the list item
is <c>{process, Pid}</c>, and for a remote process
@@ -4090,7 +4092,7 @@ os_prompt%</pre>
terminate, it has no return value - unless the arguments are
invalid, in which case the function <em>returns the error reason</em>, that is <c>badarg</c>. If you want to be
really sure not to return you can call
- <c>erlang:error(erlang:raise(Class, Reason, Stacktrace))</c>
+ <c>error(erlang:raise(Class, Reason, Stacktrace))</c>
and hope to distinguish exceptions later.</p>
</desc>
</func>
@@ -4098,7 +4100,7 @@ os_prompt%</pre>
<name>erlang:read_timer(TimerRef) -> int() | false</name>
<fsummary>Number of milliseconds remaining for a timer</fsummary>
<type>
- <v>TimerRef = ref()</v>
+ <v>TimerRef = reference()</v>
</type>
<desc>
<p><c>TimerRef</c> is a timer reference returned by
@@ -4121,7 +4123,7 @@ os_prompt%</pre>
<name>erlang:ref_to_list(Ref) -> string()</name>
<fsummary>Text representation of a reference</fsummary>
<type>
- <v>Ref = ref()</v>
+ <v>Ref = reference()</v>
</type>
<desc>
<p>Returns a string which corresponds to the text
@@ -4300,7 +4302,7 @@ true</pre>
<v>Dest = pid() | RegName </v>
<v>&nbsp;LocalPid = pid() (of a process, alive or dead, on the local node)</v>
<v>Msg = term()</v>
- <v>TimerRef = ref()</v>
+ <v>TimerRef = reference()</v>
</type>
<desc>
<p>Starts a timer which will send the message <c>Msg</c>
@@ -4513,7 +4515,7 @@ true</pre>
</desc>
</func>
<func>
- <name>spawn(Node, Module, Function, ArgumentList) -> pid()</name>
+ <name>spawn(Node, Module, Function, Args) -> pid()</name>
<fsummary>Create a new process with a function as entry point on a given node</fsummary>
<type>
<v>Node = node()</v>
@@ -4691,7 +4693,7 @@ true</pre>
<tag><c>monitor</c></tag>
<item>
<p>Monitor the new process (just like
- <seealso marker="#monitor/2">erlang:monitor/2</seealso> does).</p>
+ <seealso marker="#monitor/2">monitor/2</seealso> does).</p>
</item>
<tag><c>{priority, Level}</c></tag>
<item>
@@ -4829,7 +4831,7 @@ true</pre>
<v>&nbsp;LocalPid = pid() (of a process, alive or dead, on the local node)</v>
<v>&nbsp;RegName = atom()</v>
<v>Msg = term()</v>
- <v>TimerRef = ref()</v>
+ <v>TimerRef = reference()</v>
</type>
<desc>
<p>Starts a timer which will send the message
@@ -5175,9 +5177,9 @@ true</pre>
schedulers actually have bound as requested, call
<seealso marker="#system_info_scheduler_bindings">erlang:system_info(scheduler_bindings)</seealso>.
</p>
- <p>Schedulers can currently only be bound on newer Linux
- and Solaris systems, but more systems will be supported
- in the future.
+ <p>Schedulers can currently only be bound on newer Linux,
+ Solaris, FreeBSD, and Windows systems, but more systems will be
+ supported in the future.
</p>
<p>In order for the runtime system to be able to bind schedulers,
the CPU topology needs to be known. If the runtime system fails
@@ -5364,7 +5366,7 @@ true</pre>
<p>Returns <c>{Allocator, Version, Features, Settings}.</c></p>
<p>Types:</p>
<list type="bulleted">
- <item><c>Allocator = undefined | elib_malloc | glibc</c></item>
+ <item><c>Allocator = undefined | glibc</c></item>
<item><c>Version = [int()]</c></item>
<item><c>Features = [atom()]</c></item>
<item><c>Settings = [{Subsystem, [{Parameter, Value}]}]</c></item>
@@ -5379,7 +5381,7 @@ true</pre>
implementation used. If <c>Allocator</c> equals
<c>undefined</c>, the <c>malloc()</c> implementation
used could not be identified. Currently
- <c>elib_malloc</c> and <c>glibc</c> can be identified.</p>
+ <c>glibc</c> can be identified.</p>
</item>
<item>
<p><c>Version</c> is a list of integers (but not a
@@ -5456,6 +5458,16 @@ true</pre>
<seealso marker="#system_info_allocator_tuple">erlang:system_info({allocator, Alloc})</seealso>.
</p>
</item>
+ <tag><c>build_type</c></tag>
+ <item>
+ <p>Returns an atom describing the build type of the runtime
+ system. This is normally the atom <c>opt</c> for optimized.
+ Other possible return values are <c>debug</c>, <c>purify</c>,
+ <c>quantify</c>, <c>purecov</c>, <c>gcov</c>, <c>valgrind</c>,
+ <c>gprof</c>, and <c>lcnt</c>. Possible return values
+ may be added and/or removed at any time without prior notice.
+ </p>
+ </item>
<tag><c>c_compiler_used</c></tag>
<item>
<p>Returns a two-tuple describing the C compiler used when
@@ -5533,7 +5545,7 @@ true</pre>
<c>CpuTopology</c> type to change.
</p>
</item>
- <tag><c>{cpu_topology, defined}</c></tag>
+ <tag><marker id="system_info_cpu_topology_defined"><c>{cpu_topology, defined}</c></marker></tag>
<item>
<p>Returns the user defined <c>CpuTopology</c>. For more
information see the documentation of
@@ -5543,12 +5555,14 @@ true</pre>
argument.
</p>
</item>
- <tag><c>{cpu_topology, detected}</c></tag>
+ <tag><marker id="system_info_cpu_topology_detected"><c>{cpu_topology, detected}</c></marker></tag>
<item>
<p>Returns the automatically detected <c>CpuTopology</c>. The
emulator currently only detects the CPU topology on some newer
- linux and solaris systems. For more information see the
- documentation of the
+ Linux, Solaris, FreeBSD, and Windows systems. On Windows system with
+ more than 32 logical processors the CPU topology is not detected.
+ </p>
+ <p>For more information see the documentation of the
<seealso marker="#system_info_cpu_topology">cpu_topology</seealso>
argument.
</p>
@@ -5606,52 +5620,16 @@ true</pre>
</item>
<tag><c>elib_malloc</c></tag>
<item>
- <p>If the emulator uses the <c>elib_malloc</c> memory
- allocator, a list of two-element tuples containing status
- information is returned; otherwise, <c>false</c> is
- returned. The list currently contains the following
- two-element tuples (all sizes are presented in bytes):</p>
- <taglist>
- <tag><c>{heap_size, Size}</c></tag>
- <item>
- <p>Where <c>Size</c> is the current heap size.</p>
- </item>
- <tag><c>{max_alloced_size, Size}</c></tag>
- <item>
- <p>Where <c>Size</c> is the maximum amount of memory
- allocated on the heap since the emulator started.</p>
- </item>
- <tag><c>{alloced_size, Size}</c></tag>
- <item>
- <p>Where <c>Size</c> is the current amount of memory
- allocated on the heap.</p>
- </item>
- <tag><c>{free_size, Size}</c></tag>
- <item>
- <p>Where <c>Size</c> is the current amount of free
- memory on the heap.</p>
- </item>
- <tag><c>{no_alloced_blocks, No}</c></tag>
- <item>
- <p>Where <c>No</c> is the current number of allocated
- blocks on the heap.</p>
- </item>
- <tag><c>{no_free_blocks, No}</c></tag>
- <item>
- <p>Where <c>No</c> is the current number of free blocks
- on the heap.</p>
- </item>
- <tag><c>{smallest_alloced_block, Size}</c></tag>
- <item>
- <p>Where <c>Size</c> is the size of the smallest
- allocated block on the heap.</p>
- </item>
- <tag><c>{largest_free_block, Size}</c></tag>
- <item>
- <p>Where <c>Size</c> is the size of the largest free
- block on the heap.</p>
- </item>
- </taglist>
+ <p>This option will be removed in a future release.
+ The return value will always be <c>false</c> since
+ the elib_malloc allocator has been removed.</p>
+ </item>
+ <tag><marker id="system_info_dist_buf_busy_limit"><c>dist_buf_busy_limit</c></marker></tag>
+ <item>
+ <p>Returns the value of the distribution buffer busy limit
+ in bytes. This limit can be set on startup by passing the
+ <seealso marker="erl#+zdbbl">+zdbbl</seealso> command line
+ flag to <c>erl</c>.</p>
</item>
<tag><c>fullsweep_after</c></tag>
<item>
@@ -5727,11 +5705,34 @@ true</pre>
information see the <seealso marker="erts:crash_dump">"How to interpret the Erlang crash dumps"</seealso> chapter
in the ERTS User's Guide.</p>
</item>
- <tag><c>logical_processors</c></tag>
+ <tag><marker id="logical_processors"><c>logical_processors</c></marker></tag>
+ <item>
+ <p>Returns the detected number of logical processors configured
+ on the system. The return value is either an integer, or
+ the atom <c>unknown</c> if the emulator wasn't able to
+ detect logical processors configured.
+ </p>
+ </item>
+ <tag><marker id="logical_processors_available"><c>logical_processors_available</c></marker></tag>
<item>
- <p>Returns the number of logical processors detected on the
- system as an integer or the atom <c>unknown</c> if the
- emulator wasn't able to detect any.
+ <p>Returns the detected number of logical processors available to
+ the Erlang runtime system. The return value is either an
+ integer, or the atom <c>unknown</c> if the emulator wasn't
+ able to detect logical processors available. The number
+ of logical processors available is less than or equal to
+ the number of <seealso marker="#logical_processors_online">logical
+ processors online</seealso>.
+ </p>
+ </item>
+ <tag><marker id="logical_processors_online"><c>logical_processors_online</c></marker></tag>
+ <item>
+ <p>Returns the detected number of logical processors online on
+ the system. The return value is either an integer,
+ or the atom <c>unknown</c> if the emulator wasn't able to
+ detect logical processors online. The number of logical
+ processors online is less than or equal to the number of
+ <seealso marker="#logical_processors">logical processors
+ configured</seealso>.
</p>
</item>
<tag><c>machine</c></tag>
@@ -5936,6 +5937,26 @@ true</pre>
<c>get_tcw</c> in "Match Specifications in Erlang",
<seealso marker="erts:match_spec#get_tcw">ERTS User's Guide</seealso>.</p>
</item>
+ <tag><marker id="update_cpu_info"><c>update_cpu_info</c></marker></tag>
+ <item>
+ <p>The runtime system rereads the CPU information available and
+ updates its internally stored information about the
+ <seealso marker="#system_info_cpu_topology_detected">detected CPU
+ topology</seealso> and the amount of logical processors
+ <seealso marker="#logical_processors">configured</seealso>,
+ <seealso marker="#logical_processors_online">online</seealso>, and
+ <seealso marker="#logical_processors_available">available</seealso>.
+ If the CPU information has changed since the last time it was read,
+ the atom <c>changed</c> is returned; otherwise, the atom
+ <c>unchanged</c> is returned. If the CPU information has changed
+ you probably want to
+ <seealso marker="#system_flag_schedulers_online">adjust the amount
+ of schedulers online</seealso>. You typically want to have as
+ many schedulers online as
+ <seealso marker="#logical_processors_available">logical processors
+ available</seealso>.
+ </p>
+ </item>
<tag><marker id="system_info_version"><c>version</c></marker></tag>
<item>
<p>Returns a string containing the version number of the
diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml
index 6174917807..1703ce0942 100644
--- a/erts/doc/src/notes.xml
+++ b/erts/doc/src/notes.xml
@@ -30,6 +30,528 @@
</header>
<p>This document describes the changes made to the ERTS application.</p>
+<section><title>Erts 5.8.1.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fix that the documentation top index generator can
+ handle an Ericsson internal application group. </p>
+ <p>
+ Own Id: OTP-8875</p>
+ </item>
+ <item>
+ <p>In embedded mode, on_load handlers that called
+ <c>code:priv_dir/1</c> or other functions in <c>code</c>
+ would hang the system. Since the <c>crypto</c>
+ application now contains an on_loader handler that calls
+ <c>code:priv_dir/1</c>, including the <c>crypto</c>
+ application in the boot file would prevent the system
+ from starting.</p>
+ <p>Also extended the <c>-init_debug</c> option to print
+ information about on_load handlers being run to
+ facilitate debugging.</p>
+ <p>
+ Own Id: OTP-8902 Aux Id: seq11703 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 5.8.1.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Windows 2003 and Windows XP pre SP3 would sometimes not
+ start the Erlang R14B VM at all due to a bug in the cpu
+ topology detection. The bug affects Windows only, no
+ other platform is even remotely affected. The bug is now
+ corrected.</p>
+ <p>
+ Own Id: OTP-8876</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 5.8.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Very small floating point numbers generated errors when
+ converting from list to float in some versions of the VM,
+ this is now corrected so that i.e.
+ list_to_float("1.0e-324"). returns 0.0 in all versions of
+ Erlang.</p>
+ <p>
+ Own Id: OTP-7178</p>
+ </item>
+ <item>
+ <p>
+ Windows Vista and Windows 7 file system virtualization,
+ which makes "old style" windows programs execute in a
+ file system sandbox, was previously unintentionally
+ turned on for the Erlang VM. This is now corrected so
+ that i.e. writes to C:\Program Files\. without
+ administrator privileges will fail.</p>
+ <p>
+ Own Id: OTP-7405</p>
+ </item>
+ <item>
+ <p>
+ Fix faulty 64-bit integer term output from drivers. Large
+ 64-bits integers did not generate correct bignums and
+ could even cause emulator crash. Only affects drivers
+ using ERL_DRV_INT64 or ERL_DRV_UINT64, introduced in
+ R13B03.</p>
+ <p>
+ Own Id: OTP-8716</p>
+ </item>
+ <item>
+ <p>
+ Fixed: inet:setopts(S, [{linger,{true,2}}]) returned
+ {error,einval} for SCTP sockets. The inet_drv had a bug
+ when checking the option size.</p>
+ <p>
+ Own Id: OTP-8726 Aux Id: seq11617 </p>
+ </item>
+ <item>
+ <p>Fix libm linking with --as-needed flag
+ <p>
+ When building with "--as-needed" linker flags on Linux
+ the build will fail. This has now been fixed.</p>
+ <p>
+ (Thanks to Christian Faulhammer)</p></p>
+ <p>
+ Own Id: OTP-8728</p>
+ </item>
+ <item>
+ <p>
+ gen_udp:connect/3 was broken for SCTP enabled builds. It
+ did not detect remote end errors as it should.</p>
+ <p>
+ Own Id: OTP-8729</p>
+ </item>
+ <item>
+ <p>Reduce the risk of integer wrapping in bin vheap size
+ counting.</p> <p>The vheap size series will now use the
+ golden ratio instead of doubling and fibonacci
+ sequences.</p>
+ <p>
+ Own Id: OTP-8730</p>
+ </item>
+ <item>
+ <p>
+ ETS ordered_set containing <c>[]</c> as key could cause
+ strange thing to happen, like an infinite hanging
+ <c>ets:select</c>.</p>
+ <p>
+ Own Id: OTP-8732</p>
+ </item>
+ <item>
+ <p>reference() has been substituted for ref() in the
+ documentation.</p>
+ <p>
+ Own Id: OTP-8733</p>
+ </item>
+ <item>
+ <p>
+ When a native compiled module called a not loaded
+ non-native compiled module that had an on_load function,
+ the export entries were trashed after code loading so on
+ the next call from the native compiled module to the
+ non-native compiled the emulator crashed. This bug has
+ now been fixed.</p>
+ <p>
+ Own Id: OTP-8736</p>
+ </item>
+ <item>
+ <p>
+ HiPE-enabled Erlang VMs running on BSD systems sometimes
+ generated messages like "Yikes! erts_alloc() returned
+ misaligned address 0x8016a512c". Fixed. (Thanks to Mikael
+ Pettersson.)</p>
+ <p>
+ Own Id: OTP-8769</p>
+ </item>
+ <item>
+ <p>
+ A race condition in <c>erts_poll()</c> could cause delay
+ of poll for I/O.</p>
+ <p>
+ Own Id: OTP-8773</p>
+ </item>
+ <item>
+ <p>
+ Removed some potential vulnerabilities from the Erlang
+ Port Mapper Daemon (epmd) and straightened up access
+ control. Also removed hazardous interfaces allowing
+ anyone on a machine to forcefully unregister other nodes.
+ This means that the ei_unregister/erl_unregister
+ interfaces in erl_interface is rendered not only error
+ prone and mystifying as before, but totally ineffective.
+ The old behaviour of unchecked node unregistering can be
+ restored if needed, see epmd documentation for details.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-8780</p>
+ </item>
+ <item>
+ <p> Building in a source tree without prebuilt platform
+ independent build results failed on the SSL examples
+ when: </p> <list><item> cross building. This has been
+ solved by not building the SSL examples during a cross
+ build. </item><item> building on Windows. </item></list>
+ <p>
+ Own Id: OTP-8791</p>
+ </item>
+ <item>
+ <p>
+ inet:getsockopt for SCTP sctp_default_send_param had a
+ bug to not initialize required feilds causing random
+ answers. It is now corrected.</p>
+ <p>
+ Own Id: OTP-8795 Aux Id: seq11655 </p>
+ </item>
+ <item>
+ <p>
+ The hipe_bifs:get_hrvtime/0 BIF now always returns a real
+ value even if the "perfctr" Linux kernel extension is not
+ available. It used to return a dummy value. (Thanks to
+ Mikael Pettersson.)</p>
+ <p>
+ Own Id: OTP-8798</p>
+ </item>
+ <item>
+ <p>
+ Calling a native-code compiled module with an
+ <c>on_load</c> function could cause a crash. (Thanks to
+ Mikael Pettersson.)</p>
+ <p>
+ Own Id: OTP-8799</p>
+ </item>
+ <item>
+ <p>The emulator could crash while writing a crash dump if
+ native-compiled modules had been loaded. (Thanks to Paul
+ Guyot.)</p>
+ <p>
+ Own Id: OTP-8801</p>
+ </item>
+ <item>
+ <p>
+ The garbage collector could crash if invoked from
+ native-compiled code after a call to a BIF. (Thanks to
+ Paul Guyot.)</p>
+ <p>
+ Own Id: OTP-8821</p>
+ </item>
+ <item>
+ <p>
+ A rare memory leak in binary:matches is removed</p>
+ <p>
+ Own Id: OTP-8823</p>
+ </item>
+ <item>
+ <p>For a socket in the HTTP packet mode, the return value
+ from <c>gen_tcp:recv/2,3</c> if there is an error in the
+ header will be <c>{ok,{http_error,String}}</c> instead of
+ <c>{error,{http_error,String}}</c> to be consistent with
+ <c>ssl:recv/2,3</c>.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-8831</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ ets:select_reverse/{1,2,3} are now documented.</p>
+ <p>
+ Own Id: OTP-7863</p>
+ </item>
+ <item>
+ <p>
+ External format of integers changed to make full use of
+ all 32 bits of INTEGER_EXT. This is a compatible change
+ as old code can read full 32-bit integers but only
+ produce 28-bit integers as INTEGER_EXT.</p>
+ <p>
+ Own Id: OTP-8540 Aux Id: seq11534 </p>
+ </item>
+ <item>
+ <p>
+ Large parts of the <c>ethread</c> library have been
+ rewritten. The <c>ethread</c> library is an Erlang
+ runtime system internal, portable thread library used by
+ the runtime system itself.</p>
+ <p>
+ Most notable improvement is a reader optimized rwlock
+ implementation which dramatically improve the performance
+ of read-lock/read-unlock operations on multi processor
+ systems by avoiding ping-ponging of the rwlock cache
+ lines. The reader optimized rwlock implementation is used
+ by miscellaneous rwlocks in the runtime system that are
+ known to be read-locked frequently, and can be enabled on
+ ETS tables by passing the <seealso
+ marker="stdlib:ets#new_2_read_concurrency">{read_concurrency,
+ true}</seealso> option upon table creation. See the
+ documentation of <seealso
+ marker="stdlib:ets#new/2">ets:new/2</seealso> for more
+ information. The reader optimized rwlock implementation
+ can be fine tuned when starting the runtime system. For
+ more information, see the documentation of the <seealso
+ marker="erts:erl#+rg">+rg</seealso> command line argument
+ of <c>erl</c>.</p>
+ <p>
+ There is also a new implementation of rwlocks that is not
+ optimized for readers. Both implementations interleaves
+ readers and writers during contention as opposed to,
+ e.g., the NPTL (Linux) pthread rwlock implementation
+ which use either a reader or writer preferred strategy.
+ The reader/writer preferred strategy is problematic since
+ it starves threads doing the non-preferred operation.</p>
+ <p>
+ The new rwlock implementations in general performs better
+ in ERTS than common pthread implementations. However, in
+ some extremely heavily contended cases this is not the
+ case. Such heavy contention can more or less only appear
+ on ETS tables. This when multiple processes do very large
+ amounts of write locked operations simultaneously on the
+ same table. Such use of ETS is bad regardless of rwlock
+ implementation, will never scale, and is something we
+ strongly advise against.</p>
+ <p>
+ The new rwlock implementations depend on atomic
+ operations. If no native atomic implementation is found,
+ a fallback solution will be used. Using the fallback
+ implies a performance degradation. That is, it is more
+ important now than before to build OTP with a native
+ atomic implementation.</p>
+ <p>
+ The <c>ethread</c> library contains native atomic
+ implementations for, x86 (32 and 64 bit), powerpc (32
+ bit), sparc V9 (32 and 64 bit), and tilera (32 bit). On
+ other hardware gcc's builtin support for atomic memory
+ access will be used if such exists. If no such support is
+ found, <c>configure</c> will warn about no atomic
+ implementation available.</p>
+ <p>
+ The <c>ethread</c> library can now also use the
+ <c>libatomic_ops</c> library for atomic memory accesses.
+ This makes it possible for the Erlang runtime system to
+ utilize optimized native atomic operations on more
+ platforms than before. If <c>configure</c> warns about no
+ atomic implementation available, try using the
+ <c>libatomic_ops</c> library. Use the <seealso
+ marker="doc/installation_guide:INSTALL#How-to-Build-and-Install-ErlangOTP_A-Closer-Look-at-the-individual-Steps_Configuring">--with-libatomic_ops=PATH</seealso>
+ <c>configure</c> command line argument when specifying
+ where the <c>libatomic_ops</c> installation is located.
+ The <c>libatomic_ops</c> library can be downloaded from:
+ <url
+ href="http://www.hpl.hp.com/research/linux/atomic_ops/">http://www.hpl.hp.com/research/linux/atomic_ops/</url></p>
+ <p>
+ The changed API of the <c>ethread</c> library has also
+ caused modifications in the Erlang runtime system.
+ Preparations for the to come "delayed deallocation"
+ feature has also been done since it depends on the
+ <c>ethread</c> library.</p>
+ <p>
+ <em>Note</em>: When building for x86, the <c>ethread</c>
+ library will now use instructions that first appeared on
+ the pentium 4 processor. If you want the runtime system
+ to be compatible with older processors (back to 486) you
+ need to pass the <seealso
+ marker="doc/installation_guide:INSTALL#How-to-Build-and-Install-ErlangOTP_A-Closer-Look-at-the-individual-Steps_Configuring">--enable-ethread-pre-pentium4-compatibility</seealso>
+ <c>configure</c> command line argument when configuring
+ the system.</p>
+ <p>
+ Own Id: OTP-8544</p>
+ </item>
+ <item>
+ <p>
+ erlang:localtime_to_universaltime({{2008, 8, 1}, {0, 0,
+ 0}},true) when TZ=UTC now behaves consistently on all
+ Unix platforms.</p>
+ <p>
+ The problem fixed was originally reported by Paul Guyot
+ on erlang-bugs mailing list:</p>
+ <p>
+ http://www.erlang.org/pipermail/erlang-bugs/2008-November/001077.html</p>
+ <p>
+ Own Id: OTP-8580</p>
+ </item>
+ <item>
+ <p>
+ Optimization reducing memory consumption by two words per
+ ETS object.</p>
+ <p>
+ Own Id: OTP-8737</p>
+ </item>
+ <item>
+ <p>
+ Fixes for unsupported halfword-emulator</p>
+ <p>
+ Own Id: OTP-8745</p>
+ </item>
+ <item>
+ <p>
+ NIF 64-bit integer support; <c>enif_get_int64</c>,
+ <c>enif_get_uint64</c>, <c>enif_make_int64</c>,
+ <c>enif_make_uint64</c>.</p>
+ <p>
+ Own Id: OTP-8746</p>
+ </item>
+ <item>
+ <p>
+ Alignment of trailing data in messages has been adjusted.
+ This in order to be able to pass data of any type as
+ trailing data in the future.</p>
+ <p>
+ Own Id: OTP-8754</p>
+ </item>
+ <item>
+ <p>
+ The obsolete/driver.h header file has been removed. It
+ has been obsolete and deprecated since R8B. Drivers that
+ still include obsolete/driver.h must be updated to
+ include erl_driver.h.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-8758</p>
+ </item>
+ <item>
+ <p>
+ Added erlang:system_info(build_type) which makes it
+ easier to chose drivers, NIF libraries, etc based on
+ build type of the runtime system.</p>
+ <p>
+ The NIF library for crypto can now be built for valgrind
+ and/or debug as separate NIF libraries that will be
+ automatically loaded if the runtime system has been built
+ with a matching build type.</p>
+ <p>
+ Own Id: OTP-8760</p>
+ </item>
+ <item>
+ <p>
+ Further lessened the memory requirements of ETS objects.</p>
+ <p>
+ Own Id: OTP-8762</p>
+ </item>
+ <item>
+ <p>The broken elib_malloc alternate memory allocator has
+ been removed. <c>erlang:system_info(elib_malloc)</c> will
+ always return <c>false</c>, and in R15,
+ <c>erlang:system_info(elib_malloc)</c> will fail with a
+ <c>badarg</c> exception.</p>
+ <p>
+ Own Id: OTP-8764</p>
+ </item>
+ <item>
+ <p>
+ Calling <c>erlang:system_info/1</c> with the new argument
+ <c>update_cpu_info</c> will make the runtime system
+ reread and update the internally stored CPU information.
+ For more information see the documentation of <seealso
+ marker="erlang#update_cpu_info">erlang:system_info(update_cpu_info)</seealso>.</p>
+ <p>
+ The CPU topology is now automatically detected on Windows
+ systems with less than 33 logical processors. The runtime
+ system will now, also on Windows, by default bind
+ schedulers to logical processors using the
+ <c>default_bind</c> bind type if the amount of schedulers
+ is at least equal to the amount of logical processors
+ configured, binding of schedulers is supported, and a CPU
+ topology is available at startup.</p>
+ <p>
+ Own Id: OTP-8765</p>
+ </item>
+ <item>
+ <p>
+ The SMP ERTS internal child waiter thread used on Linux
+ system with NPTL was unintentionally disabled during
+ cross compilation rewrites (OTP-8323 in R13B03). It has
+ now been re-enabled. Enabling it again gives a slight
+ performance improvement.</p>
+ <p>
+ Own Id: OTP-8774</p>
+ </item>
+ <item>
+ <p>
+ <c>epmd</c> used to generate a message to the syslog when
+ it started up, which could be annoying. This has been
+ changed to only generate the message if the debug swith
+ is given. (Thanks to Michael Santos.)</p>
+ <p>
+ Own Id: OTP-8775</p>
+ </item>
+ <item>
+ <p>
+ The scheduler wakeup threshold is now possible to adjust
+ at system boot. For more information see the <seealso
+ marker="erl#+swt">+swt</seealso> command line argument of
+ <c>erl</c>.</p>
+ <p>
+ Own Id: OTP-8811</p>
+ </item>
+ <item>
+ <p>
+ The undocumented function inet:ifget/2 has been improved
+ to return interface hardware address (MAC) on platforms
+ supporting getaddrinfo() (such as BSD unixes). Note it
+ still does not work on all platforms for example not
+ Windows nor Solaris, so the function is still
+ undocumented.</p>
+ <p>
+ Buffer overflow and field init bugs for inet:ifget/2 and
+ inet:getservbyname/2 has also been fixed.</p>
+ <p>
+ Thanks to Michael Santos.</p>
+ <p>
+ Own Id: OTP-8816</p>
+ </item>
+ <item>
+ <p>
+ Optimizations for MIPS when using gcc atomics. (Thanks to
+ Steve Vinoski)</p>
+ <p>
+ Own Id: OTP-8834</p>
+ </item>
+ <item>
+ <p>
+ Lock optimization in timer functionality.</p>
+ <p>
+ Own Id: OTP-8835</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Known Bugs and Problems</title>
+ <list>
+ <item>
+ <p>Fix epmd and build environment to build on VxWorks</p>
+ <p>
+ Own Id: OTP-8838</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erts 5.8</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in
index 2b9f70b0f4..76d782b159 100644
--- a/erts/emulator/Makefile.in
+++ b/erts/emulator/Makefile.in
@@ -74,7 +74,7 @@ else
ifeq ($(TYPE),gcov)
PURIFY =
TYPEMARKER = .gcov
-TYPE_FLAGS = @DEBUG_CFLAGS@ -DNO_JUMP_TABLE -fprofile-arcs -ftest-coverage -O0 -DERTS_CAN_INLINE=0 -DERTS_INLINE=
+TYPE_FLAGS = @DEBUG_CFLAGS@ -DERTS_GCOV -DNO_JUMP_TABLE -fprofile-arcs -ftest-coverage -O0 -DERTS_CAN_INLINE=0 -DERTS_INLINE=
ifneq ($(findstring solaris,$(TARGET)),solaris)
LIBS += -lgcov
endif
@@ -293,8 +293,6 @@ endif
DEPLIBS += $(ERL_TOP)/erts/emulator/pcre/obj/$(TARGET)/$(TYPE)/$(LIB_PREFIX)epcre$(LIB_SUFFIX)
-ELIB_FLAGS = -DENABLE_ELIB_MALLOC -DELIB_ALLOC_IS_CLIB -DELIB_HEAP_SBRK
-
PERFCTR_PATH=@PERFCTR_PATH@
USE_PERFCTR=@USE_PERFCTR@
ifdef PERFCTR_PATH
@@ -460,8 +458,6 @@ release_spec: all
ifeq ($(ERLANG_OSTYPE), unix)
$(INSTALL_PROGRAM) $(BINDIR)/$(CS_EXECUTABLE) $(RELSYSDIR)/bin
endif
- $(INSTALL_DIR) $(RELEASE_PATH)/usr/include/obsolete
- $(INSTALL_DATA) obsolete/driver.h $(RELEASE_PATH)/usr/include/obsolete
endif
endif
@@ -535,8 +531,9 @@ TABLES= $(TARGET)/erl_bif_table.c $(TARGET)/erl_bif_table.h \
$(TARGET)/erl_atom_table.c $(TARGET)/erl_atom_table.h \
$(TARGET)/erl_pbifs.c
-$(TABLES): $(ATOMS) $(BIFS)
- LANG=C $(PERL) utils/make_tables -src $(TARGET) -include $(TARGET) $^
+$(TABLES): $(ATOMS) $(BIFS) utils/make_tables
+ LANG=C $(PERL) utils/make_tables -src $(TARGET) -include $(TARGET)\
+ $(ATOMS) $(BIFS)
$(TTF_DIR)/erl_alloc_types.h: beam/erl_alloc.types utils/make_alloc_types
LANG=C $(PERL) utils/make_alloc_types -src $< -dst $@ $(ENABLE_ALLOC_TYPE_VARS)
@@ -655,9 +652,6 @@ $(BINDIR)/$(CS_EXECUTABLE): $(CS_SRC)
$(CS_PURIFY) $(CC) $(CS_LDFLAGS) -o $(BINDIR)/$(CS_EXECUTABLE) \
$(CS_CFLAGS) $(COMMON_INCLUDES) $(CS_SRC) $(CS_LIBS)
-$(OBJDIR)/%.elib.o: beam/%.c
- $(CC) $(ELIB_FLAGS) $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@
-
$(OBJDIR)/%.kp.o: sys/common/%.c
$(CC) -DERTS_KERNEL_POLL_VERSION $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@
@@ -666,9 +660,6 @@ $(OBJDIR)/%.nkp.o: sys/common/%.c
ifeq ($(GCC),yes)
-$(OBJDIR)/erl_obsolete.o: beam/erl_obsolete.c
- $(CC) $(subst -Wstrict-prototypes, , $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS))) $(INCLUDES) -c $< -o $@
-
$(OBJDIR)/erl_goodfit_alloc.o: beam/erl_goodfit_alloc.c
$(CC) $(subst -O2, $(GEN_OPT_FLGS) $(UNROLL_FLG), $(CFLAGS)) $(INCLUDES) -c $< -o $@
endif
@@ -743,7 +734,7 @@ RUN_OBJS = \
$(OBJDIR)/erl_fun.o $(OBJDIR)/erl_bif_port.o \
$(OBJDIR)/erl_term.o $(OBJDIR)/erl_node_tables.o \
$(OBJDIR)/erl_monitors.o $(OBJDIR)/erl_process_dump.o \
- $(OBJDIR)/erl_obsolete.o $(OBJDIR)/erl_bif_timer.o \
+ $(OBJDIR)/erl_bif_timer.o \
$(OBJDIR)/erl_drv_thread.o $(OBJDIR)/erl_bif_chksum.o \
$(OBJDIR)/erl_bif_re.o $(OBJDIR)/erl_unicode.o \
$(OBJDIR)/packet_parser.o $(OBJDIR)/safe_hash.o \
@@ -767,15 +758,13 @@ OS_OBJS = \
$(OBJDIR)/sys_time.o \
$(OBJDIR)/sys_interrupt.o \
$(OBJDIR)/sys_env.o \
- $(OBJDIR)/dosmap.o \
- $(OBJDIR)/elib_malloc.o
+ $(OBJDIR)/dosmap.o
else
OS_OBJS = \
$(OBJDIR)/sys.o \
$(OBJDIR)/driver_tab.o \
$(OBJDIR)/unix_efile.o \
$(OBJDIR)/gzio.o \
- $(OBJDIR)/elib_malloc.o \
$(OBJDIR)/elib_memmove.o
ifeq ($(findstring vxworks,$(TARGET)),vxworks)
@@ -839,16 +828,6 @@ BASE_OBJS = $(RUN_OBJS) $(EMU_OBJS) $(OS_OBJS) $(EXTRA_BASE_OBJS)
OBJS = $(BASE_OBJS) $(DRV_OBJS)
-ELIB_C_FILES = beam/elib_malloc.c \
- beam/elib_memmove.c \
- beam/erl_bif_info.c \
- beam/utils.c \
- beam/erl_alloc.c
-
-MOD_OBJS_ELIB = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(ELIB_C_FILES)))
-OBJS_ELIB = $(patsubst %.o,%.elib.o,$(MOD_OBJS_ELIB)) \
- $(filter-out $(MOD_OBJS_ELIB),$(OBJS))
-
########################################
# HiPE section
@@ -940,10 +919,6 @@ $(BINDIR)/$(EMULATOR_EXECUTABLE): $(INIT_OBJS) $(OBJS) $(DEPLIBS)
$(PURIFY) $(LD) -o $(BINDIR)/$(EMULATOR_EXECUTABLE) \
$(HIPEBEAMLDFLAGS) $(LDFLAGS) $(DEXPORT) $(INIT_OBJS) $(OBJS) $(LIBS)
-$(BINDIR)/$(EMULATOR_EXECUTABLE_ELIB): $(INIT_OBJS) $(OBJS_ELIB) $(DEPLIBS)
- $(PURIFY) $(LD) -o $(BINDIR)/$(EMULATOR_EXECUTABLE_ELIB) \
- $(LDFLAGS) $(DEXPORT) $(INIT_OBJS) $(OBJS_ELIB) $(LIBS)
-
endif
#
@@ -1038,7 +1013,7 @@ depend:
$(DEP_CC) $(DEP_FLAGS) $(TARGET_SRC) \
| $(SED_DEPEND) >> $(TARGET)/depend.mk
ifneq ($(TARGET),win32)
- $(DEP_CC) $(DEP_FLAGS) $(ELIB_FLAGS) $(ELIB_C_FILES) \
+ $(DEP_CC) $(DEP_FLAGS) $(ELIB_C_FILES) \
| $(SED_ELIB_DEPEND) >> $(TARGET)/depend.mk
endif
ifdef HIPE_ENABLED
diff --git a/erts/emulator/beam/atom.c b/erts/emulator/beam/atom.c
index 6b3c106a97..b97705ed96 100644
--- a/erts/emulator/beam/atom.c
+++ b/erts/emulator/beam/atom.c
@@ -303,7 +303,7 @@ init_atom_table(void)
HashFunctions f;
int i;
Atom a;
- erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_THR_OPTS_DEFAULT_INITER;
+ erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER;
rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ;
rwmtx_opt.lived = ERTS_SMP_RWMTX_LONG_LIVED;
diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names
index 0815cdbc7f..327620772f 100644
--- a/erts/emulator/beam/atom.names
+++ b/erts/emulator/beam/atom.names
@@ -119,6 +119,7 @@ atom bsl
atom bsr
atom bsr_anycrlf
atom bsr_unicode
+atom build_type
atom busy_dist_port
atom busy_port
atom call
@@ -378,6 +379,7 @@ atom old_heap_size
atom on_load
atom open
atom open_error
+atom opt
atom or
atom ordered_set
atom orelse
diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c
index 4fc271d41c..6ae9736141 100644
--- a/erts/emulator/beam/beam_bif_load.c
+++ b/erts/emulator/beam/beam_bif_load.c
@@ -337,7 +337,6 @@ BIF_RETTYPE finish_after_on_load_2(BIF_ALIST_2)
ep->code[0] == BIF_ARG_1 &&
ep->code[4] != 0) {
ep->address = (void *) ep->code[4];
- ep->code[3] = 0;
ep->code[4] = 0;
}
}
diff --git a/erts/emulator/beam/beam_debug.c b/erts/emulator/beam/beam_debug.c
index 23b267d5cd..b0bf14b94f 100644
--- a/erts/emulator/beam/beam_debug.c
+++ b/erts/emulator/beam/beam_debug.c
@@ -125,7 +125,7 @@ erts_debug_breakpoint_2(Process* p, Eterm MFA, Eterm bool)
BIF_ERROR(p, BADARG);
}
-#if 0 /* XXX:PaN - not used */
+#if 0 /* Kept for conveninence when hard debugging. */
void debug_dump_code(BeamInstr *I, int num)
{
BeamInstr *code_ptr = I;
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index 260f349563..8a0e12dd4f 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -3390,7 +3390,7 @@ apply_bif_or_nif_epilogue:
pb->val = bptr;
pb->bytes = (byte*) bptr->orig_bytes;
pb->flags = 0;
- MSO(c_p).overhead += pb->size / sizeof(Eterm);
+ OH_OVERHEAD(&(MSO(c_p)), pb->size / sizeof(Eterm));
new_binary = make_binary(pb);
goto do_bits_sub_bin;
}
@@ -3492,7 +3492,7 @@ apply_bif_or_nif_epilogue:
pb->bytes = (byte*) bptr->orig_bytes;
pb->flags = 0;
- MSO(c_p).overhead += tmp_arg1 / sizeof(Eterm);
+ OH_OVERHEAD(&(MSO(c_p)), tmp_arg1 / sizeof(Eterm));
StoreBifResult(2, make_binary(pb));
}
@@ -4373,7 +4373,7 @@ apply_bif_or_nif_epilogue:
ASSERT(is_CP((BeamInstr)(ep->code)));
ASSERT(is_internal_pid(c_p->tracer_proc) ||
is_internal_port(c_p->tracer_proc));
- E[2] = make_cp(c_p->cp); /* XXX:PaN - code in lower range on halfword */
+ E[2] = make_cp(c_p->cp); /* Code in lower range on halfword */
E[1] = am_true; /* Process tracer */
E[0] = make_cp(ep->code);
c_p->cp = (flags & MATCH_SET_EXCEPTION_TRACE)
@@ -4889,7 +4889,7 @@ apply_bif_or_nif_epilogue:
neg_o_reds = -c_p->def_arg_reg[4];
FCALLS = c_p->fcalls;
SWAPIN;
- switch( c_p->def_arg_reg[3] ) { /* XXX:PaN - Halfword wont work with hipe yet... */
+ switch( c_p->def_arg_reg[3] ) { /* Halfword wont work with hipe yet! */
case HIPE_MODE_SWITCH_RES_RETURN:
ASSERT(is_value(reg[0]));
MoveReturn(reg[0], r(0));
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index 30f276b95a..df5602b040 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -1379,8 +1379,10 @@ read_code_header(LoaderState* stp)
stp->ci = MI_FUNCTIONS + stp->num_functions + 1;
stp->code[MI_ATTR_PTR] = 0;
+ stp->code[MI_ATTR_SIZE] = 0;
stp->code[MI_ATTR_SIZE_ON_HEAP] = 0;
stp->code[MI_COMPILE_PTR] = 0;
+ stp->code[MI_COMPILE_SIZE] = 0;
stp->code[MI_COMPILE_SIZE_ON_HEAP] = 0;
stp->code[MI_NUM_BREAKPOINTS] = 0;
@@ -1566,7 +1568,8 @@ load_code(LoaderState* stp)
case 0: /* Floating point number */
{
Eterm* hp;
-#if !defined(ARCH_64) || HALFWORD_HEAP /* XXX:PaN - Should use ARCH_64 variant instead */
+/* XXX:PaN - Halfword should use ARCH_64 variant instead */
+#if !defined(ARCH_64) || HALFWORD_HEAP
Uint high, low;
# endif
last_op->a[arg].val = new_literal(stp, &hp,
@@ -1933,7 +1936,7 @@ load_code(LoaderState* stp)
}
code[ci++] = (BeamInstr) stp->import[i].bf;
break;
- case 'P': /* Byte offset into tuple */ /* XXX:PaN - * sizeof(Eterm or Eterm *) ? */
+ case 'P': /* Byte offset into tuple */
VerifyTag(stp, tag, TAG_u);
tmp = tmp_op->a[arg].val;
code[ci++] = (BeamInstr) ((tmp_op->a[arg].val+1) * sizeof(Eterm));
@@ -5198,8 +5201,10 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
code[MI_NUM_FUNCTIONS] = n;
code[MI_ATTR_PTR] = 0;
+ code[MI_ATTR_SIZE] = 0;
code[MI_ATTR_SIZE_ON_HEAP] = 0;
code[MI_COMPILE_PTR] = 0;
+ code[MI_COMPILE_SIZE] = 0;
code[MI_COMPILE_SIZE_ON_HEAP] = 0;
code[MI_NUM_BREAKPOINTS] = 0;
code[MI_ON_LOAD_FUNCTION_PTR] = 0;
diff --git a/erts/emulator/beam/bif.h b/erts/emulator/beam/bif.h
index 50f5f4fbd6..a84ee7bb23 100644
--- a/erts/emulator/beam/bif.h
+++ b/erts/emulator/beam/bif.h
@@ -135,7 +135,6 @@ do { \
(Proc)->arity = 1; \
(Proc)->def_arg_reg[0] = (Eterm) (A0); \
*((UWord *) (UWord) ((Proc)->def_arg_reg + 3)) = (UWord) ((Trap)->address); \
- (Proc)->def_arg_reg[3] = (UWord) ((Trap)->address); \
(Proc)->freason = TRAP; \
(Ret) = THE_NON_VALUE; \
} while (0)
@@ -146,7 +145,6 @@ do { \
(Proc)->def_arg_reg[0] = (Eterm) (A0); \
(Proc)->def_arg_reg[1] = (Eterm) (A1); \
*((UWord *) (UWord) ((Proc)->def_arg_reg + 3)) = (UWord) ((Trap)->address); \
- (Proc)->def_arg_reg[3] = (UWord) ((Trap)->address); \
(Proc)->freason = TRAP; \
(Ret) = THE_NON_VALUE; \
} while (0)
@@ -158,7 +156,6 @@ do { \
(Proc)->def_arg_reg[1] = (Eterm) (A1); \
(Proc)->def_arg_reg[2] = (Eterm) (A2); \
*((UWord *) (UWord) ((Proc)->def_arg_reg + 3)) = (UWord) ((Trap)->address); \
- (Proc)->def_arg_reg[3] = (UWord) ((Trap)->address); \
(Proc)->freason = TRAP; \
(Ret) = THE_NON_VALUE; \
} while (0)
diff --git a/erts/emulator/beam/big.c b/erts/emulator/beam/big.c
index 2d250f32cf..ff15d834ab 100644
--- a/erts/emulator/beam/big.c
+++ b/erts/emulator/beam/big.c
@@ -1881,6 +1881,9 @@ term_to_Uint(Eterm term, Uint *up)
int
term_to_UWord(Eterm term, UWord *up)
{
+#if SIZEOF_VOID_P == ERTS_SIZEOF_ETERM
+ return term_to_Uint(term,up);
+#else
if (is_small(term)) {
Sint i = signed_val(term);
if (i < 0) {
@@ -1903,7 +1906,47 @@ term_to_UWord(Eterm term, UWord *up)
return 0;
}
while (xl-- > 0) {
- uval |= ((Uint)(*xr++)) << n;
+ uval |= ((UWord)(*xr++)) << n;
+ n += D_EXP;
+ }
+ *up = uval;
+ return 1;
+ } else {
+ *up = BADARG;
+ return 0;
+ }
+#endif
+}
+
+int
+term_to_Uint64(Eterm term, Uint64 *up)
+{
+#if SIZEOF_VOID_P == 8
+ return term_to_UWord(term,up);
+#else
+ if (is_small(term)) {
+ Sint i = signed_val(term);
+ if (i < 0) {
+ *up = BADARG;
+ return 0;
+ }
+ *up = (Uint64) i;
+ return 1;
+ } else if (is_big(term)) {
+ ErtsDigit* xr = big_v(term);
+ dsize_t xl = big_size(term);
+ Uint64 uval = 0;
+ int n = 0;
+
+ if (big_sign(term)) {
+ *up = BADARG;
+ return 0;
+ } else if (xl*D_EXP > sizeof(Uint64)*8) {
+ *up = SYSTEM_LIMIT;
+ return 0;
+ }
+ while (xl-- > 0) {
+ uval |= ((Uint64)(*xr++)) << n;
n += D_EXP;
}
*up = uval;
@@ -1912,8 +1955,10 @@ term_to_UWord(Eterm term, UWord *up)
*up = BADARG;
return 0;
}
+#endif
}
+
int term_to_Sint(Eterm term, Sint *sp)
{
if (is_small(term)) {
@@ -1948,6 +1993,47 @@ int term_to_Sint(Eterm term, Sint *sp)
}
}
+#if HAVE_INT64
+int term_to_Sint64(Eterm term, Sint64 *sp)
+{
+#if ERTS_SIZEOF_ETERM == 8
+ return term_to_Sint(term, sp);
+#else
+ if (is_small(term)) {
+ *sp = signed_val(term);
+ return 1;
+ } else if (is_big(term)) {
+ ErtsDigit* xr = big_v(term);
+ dsize_t xl = big_size(term);
+ int sign = big_sign(term);
+ Uint64 uval = 0;
+ int n = 0;
+
+ if (xl*D_EXP > sizeof(Uint64)*8) {
+ return 0;
+ }
+ while (xl-- > 0) {
+ uval |= ((Uint64)(*xr++)) << n;
+ n += D_EXP;
+ }
+ if (sign) {
+ uval = -uval;
+ if ((Sint64)uval > 0)
+ return 0;
+ } else {
+ if ((Sint64)uval < 0)
+ return 0;
+ }
+ *sp = uval;
+ return 1;
+ } else {
+ return 0;
+ }
+#endif
+}
+#endif /* HAVE_INT64 */
+
+
/*
** Add and subtract
*/
diff --git a/erts/emulator/beam/big.h b/erts/emulator/beam/big.h
index 56f3be372a..25466cd3c2 100644
--- a/erts/emulator/beam/big.h
+++ b/erts/emulator/beam/big.h
@@ -152,6 +152,10 @@ byte* big_to_bytes(Eterm, byte*);
int term_to_Uint(Eterm, Uint*);
int term_to_UWord(Eterm, UWord*);
int term_to_Sint(Eterm, Sint*);
+#if HAVE_INT64
+int term_to_Uint64(Eterm, Uint64*);
+int term_to_Sint64(Eterm, Sint64*);
+#endif
Uint32 big_to_uint32(Eterm b);
int term_equals_2pow32(Eterm);
diff --git a/erts/emulator/beam/binary.c b/erts/emulator/beam/binary.c
index 3fd714f9c2..8ee8fbcb29 100644
--- a/erts/emulator/beam/binary.c
+++ b/erts/emulator/beam/binary.c
@@ -97,7 +97,7 @@ new_binary(Process *p, byte *buf, int len)
/*
* Miscellanous updates. Return the tagged binary.
*/
- MSO(p).overhead += pb->size / sizeof(Eterm);
+ OH_OVERHEAD(&(MSO(p)), pb->size / sizeof(Eterm));
return make_binary(pb);
}
@@ -136,7 +136,7 @@ Eterm erts_new_mso_binary(Process *p, byte *buf, int len)
/*
* Miscellanous updates. Return the tagged binary.
*/
- MSO(p).overhead += pb->size / sizeof(Eterm);
+ OH_OVERHEAD(&(MSO(p)), pb->size / sizeof(Eterm));
return make_binary(pb);
}
diff --git a/erts/emulator/beam/copy.c b/erts/emulator/beam/copy.c
index 57be0169ba..8bee47232e 100644
--- a/erts/emulator/beam/copy.c
+++ b/erts/emulator/beam/copy.c
@@ -317,7 +317,7 @@ copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
pb->next = off_heap->first;
pb->flags = 0;
off_heap->first = (struct erl_off_heap_header*) pb;
- off_heap->overhead += pb->size / sizeof(Eterm);
+ OH_OVERHEAD(off_heap, pb->size / sizeof(Eterm));
}
break;
case SUB_BINARY_SUBTAG:
@@ -366,7 +366,7 @@ copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
to->next = off_heap->first;
to->flags = 0;
off_heap->first = (struct erl_off_heap_header*) to;
- off_heap->overhead += to->size / sizeof(Eterm);
+ OH_OVERHEAD(off_heap, to->size / sizeof(Eterm));
}
*argp = make_binary(hbot);
if (extra_bytes != 0) {
@@ -652,7 +652,7 @@ Eterm copy_struct_lazy(Process *from, Eterm orig, Uint offs)
erts_refc_inc(&pb->val->refc, 2);
pb->next = erts_global_offheap.first;
erts_global_offheap.first = pb;
- erts_global_offheap.overhead += pb->size / sizeof(Eterm);
+ OH_OVERHEAD(off_heap, pb->size / sizeof(Eterm));
continue;
}
@@ -777,7 +777,7 @@ Eterm copy_struct_lazy(Process *from, Eterm orig, Uint offs)
to_bin->bytes = from_bin->bytes + sub_offset;
to_bin->next = erts_global_offheap.first;
erts_global_offheap.first = to_bin;
- erts_global_offheap.overhead += to_bin->size / sizeof(Eterm);
+ OH_OVERHEAD(&erts_global_offheap, to_bin->size / sizeof(Eterm));
res_binary=make_binary(to_bin);
hp += PROC_BIN_SIZE;
}
@@ -912,7 +912,7 @@ copy_shallow(Eterm* ptr, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
{
ProcBin* pb = (ProcBin *) (tp-1);
erts_refc_inc(&pb->val->refc, 2);
- off_heap->overhead += pb->size / sizeof(Eterm);
+ OH_OVERHEAD(off_heap, pb->size / sizeof(Eterm));
}
goto off_heap_common;
@@ -977,7 +977,7 @@ void move_multi_frags(Eterm** hpp, ErlOffHeap* off_heap, ErlHeapFragment* first,
for (bp=first; bp!=NULL; bp=bp->next) {
move_one_frag(hpp, bp->mem, bp->used_size, off_heap);
- off_heap->overhead += bp->off_heap.overhead;
+ OH_OVERHEAD(off_heap, bp->off_heap.overhead);
}
hp_end = *hpp;
for (hp=hp_start; hp<hp_end; ++hp) {
diff --git a/erts/emulator/beam/decl.h b/erts/emulator/beam/decl.h
deleted file mode 100644
index da1be29d53..0000000000
--- a/erts/emulator/beam/decl.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1996-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%
- */
-
-#ifndef __DECL_H__
-#define __DECL_H__
-
-#if defined(__STDC__) || defined(_MSC_VER)
-#define EXTERN_FUNCTION(t, f, x) extern t f x
-#define FUNCTION(t, f, x) t f x
-#define _DOTS_ ...
-#define _VOID_ void
-#elif defined(__cplusplus)
-#define EXTERN_FUNCTION(f, x) extern "C" { f x }
-#define FUNCTION(t, f, x) t f x
-#define _DOTS_ ...
-#define _VOID_ void
-#else
-#define EXTERN_FUNCTION(t, f, x) extern t f (/*x*/)
-#define FUNCTION(t, f, x) t f (/*x*/)
-#define _DOTS_
-#define _VOID_
-#endif
-
-/*
-** Example of declarations
-**
-** EXTERN_FUNCTION(void, foo, (int, int, char));
-** FUNCTION(void, bar, (int, char));
-**
-** struct funcs {
-** FUNCTION(int*, (*f1), (int, int));
-** FUNCTION(void, (*f2), (int, char));
-** FUNCTION(void, (*f3), (_VOID_));
-** FUNCTION(int, (*f4), (char*, _DOTS_));
-** };
-**
-*/
-
-#endif
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index 16b6aeac3f..694460d702 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -97,6 +97,8 @@ dist_msg_dbg(ErtsDistExternal *edep, char *what, byte *buf, int sz)
#define PASS_THROUGH 'p' /* This code should go */
int erts_is_alive; /* System must be blocked on change */
+int erts_dist_buf_busy_limit;
+
/* distribution trap functions */
Export* dsend2_trap = NULL;
@@ -160,7 +162,7 @@ Uint erts_dist_cache_size(void)
static ErtsProcList *
get_suspended_on_de(DistEntry *dep, Uint32 unset_qflgs)
{
- ERTS_SMP_LC_ASSERT(erts_smp_lc_spinlock_is_locked(&dep->qlock));
+ ERTS_SMP_LC_ASSERT(erts_smp_lc_mtx_is_locked(&dep->qlock));
dep->qflgs &= ~unset_qflgs;
if (dep->qflgs & ERTS_DE_QFLG_EXIT) {
/* No resume when exit has been scheduled */
@@ -453,17 +455,17 @@ int erts_do_net_exits(DistEntry *dep, Eterm reason)
if (dep->status & ERTS_DE_SFLG_EXITING) {
#ifdef DEBUG
- erts_smp_spin_lock(&dep->qlock);
+ erts_smp_mtx_lock(&dep->qlock);
ASSERT(dep->qflgs & ERTS_DE_QFLG_EXIT);
- erts_smp_spin_unlock(&dep->qlock);
+ erts_smp_mtx_unlock(&dep->qlock);
#endif
}
else {
dep->status |= ERTS_DE_SFLG_EXITING;
- erts_smp_spin_lock(&dep->qlock);
+ erts_smp_mtx_lock(&dep->qlock);
ASSERT(!(dep->qflgs & ERTS_DE_QFLG_EXIT));
dep->qflgs |= ERTS_DE_QFLG_EXIT;
- erts_smp_spin_unlock(&dep->qlock);
+ erts_smp_mtx_unlock(&dep->qlock);
}
erts_smp_de_links_lock(dep);
@@ -577,7 +579,7 @@ static void clear_dist_entry(DistEntry *dep)
erts_smp_de_links_unlock(dep);
#endif
- erts_smp_spin_lock(&dep->qlock);
+ erts_smp_mtx_lock(&dep->qlock);
if (!dep->out_queue.last)
obuf = dep->finalized_out_queue.first;
@@ -593,7 +595,7 @@ static void clear_dist_entry(DistEntry *dep)
dep->status = 0;
suspendees = get_suspended_on_de(dep, ERTS_DE_QFLGS_ALL);
- erts_smp_spin_unlock(&dep->qlock);
+ erts_smp_mtx_unlock(&dep->qlock);
erts_smp_atomic_set(&dep->dist_cmd_scheduled, 0);
dep->send = NULL;
erts_smp_de_rwunlock(dep);
@@ -611,10 +613,10 @@ static void clear_dist_entry(DistEntry *dep)
}
if (obufsize) {
- erts_smp_spin_lock(&dep->qlock);
+ erts_smp_mtx_lock(&dep->qlock);
ASSERT(dep->qsize >= obufsize);
dep->qsize -= obufsize;
- erts_smp_spin_unlock(&dep->qlock);
+ erts_smp_mtx_unlock(&dep->qlock);
}
}
@@ -1453,8 +1455,6 @@ int erts_net_message(Port *prt,
return -1;
}
-#define ERTS_DE_BUSY_LIMIT (128*1024)
-
static int
dsig_send(ErtsDSigData *dsdp, Eterm ctl, Eterm msg, int force_busy)
{
@@ -1538,18 +1538,18 @@ dsig_send(ErtsDSigData *dsdp, Eterm ctl, Eterm msg, int force_busy)
}
else {
ErtsProcList *plp = NULL;
- erts_smp_spin_lock(&dep->qlock);
+ erts_smp_mtx_lock(&dep->qlock);
dep->qsize += size_obuf(obuf);
- if (dep->qsize >= ERTS_DE_BUSY_LIMIT)
+ if (dep->qsize >= erts_dist_buf_busy_limit)
dep->qflgs |= ERTS_DE_QFLG_BUSY;
if (!force_busy && (dep->qflgs & ERTS_DE_QFLG_BUSY)) {
- erts_smp_spin_unlock(&dep->qlock);
+ erts_smp_mtx_unlock(&dep->qlock);
plp = erts_proclist_create(c_p);
plp->next = NULL;
erts_suspend(c_p, ERTS_PROC_LOCK_MAIN, NULL);
suspended = 1;
- erts_smp_spin_lock(&dep->qlock);
+ erts_smp_mtx_lock(&dep->qlock);
}
/* Enqueue obuf on dist entry */
@@ -1575,7 +1575,7 @@ dsig_send(ErtsDSigData *dsdp, Eterm ctl, Eterm msg, int force_busy)
}
}
- erts_smp_spin_unlock(&dep->qlock);
+ erts_smp_mtx_unlock(&dep->qlock);
erts_schedule_dist_command(NULL, dep);
erts_smp_de_runlock(dep);
@@ -1708,10 +1708,8 @@ erts_dist_command(Port *prt, int reds_limit)
{
Sint reds = ERTS_PORT_REDS_DIST_CMD_START;
int prt_busy;
- int de_busy;
Uint32 status;
Uint32 flags;
- Uint32 qflgs;
Sint obufsize = 0;
ErtsDistOutputQueue oq, foq;
DistEntry *dep = prt->dist_entry;
@@ -1746,13 +1744,12 @@ erts_dist_command(Port *prt, int reds_limit)
* a mess.
*/
- erts_smp_spin_lock(&dep->qlock);
+ erts_smp_mtx_lock(&dep->qlock);
oq.first = dep->out_queue.first;
oq.last = dep->out_queue.last;
dep->out_queue.first = NULL;
dep->out_queue.last = NULL;
- qflgs = dep->qflgs;
- erts_smp_spin_unlock(&dep->qlock);
+ erts_smp_mtx_unlock(&dep->qlock);
foq.first = dep->finalized_out_queue.first;
foq.last = dep->finalized_out_queue.last;
@@ -1763,17 +1760,8 @@ erts_dist_command(Port *prt, int reds_limit)
goto preempted;
prt_busy = (int) (prt->status & ERTS_PORT_SFLG_PORT_BUSY);
- de_busy = (int) (qflgs & ERTS_DE_QFLG_BUSY);
- if (prt_busy) {
- if (!de_busy) {
- erts_smp_spin_lock(&dep->qlock);
- dep->qflgs |= ERTS_DE_QFLG_BUSY;
- erts_smp_spin_unlock(&dep->qlock);
- de_busy = 1;
- }
- }
- else if (foq.first) {
+ if (!prt_busy && foq.first) {
int preempt = 0;
do {
Uint size;
@@ -1791,10 +1779,7 @@ erts_dist_command(Port *prt, int reds_limit)
free_dist_obuf(fob);
preempt = reds > reds_limit || (prt->status & ERTS_PORT_SFLGS_DEAD);
if (prt->status & ERTS_PORT_SFLG_PORT_BUSY) {
- erts_smp_spin_lock(&dep->qlock);
- dep->qflgs |= ERTS_DE_QFLG_BUSY;
- erts_smp_spin_unlock(&dep->qlock);
- de_busy = prt_busy = 1;
+ prt_busy = 1;
break;
}
} while (foq.first && !preempt);
@@ -1877,10 +1862,7 @@ erts_dist_command(Port *prt, int reds_limit)
free_dist_obuf(fob);
preempt = reds > reds_limit || (prt->status & ERTS_PORT_SFLGS_DEAD);
if (prt->status & ERTS_PORT_SFLG_PORT_BUSY) {
- erts_smp_spin_lock(&dep->qlock);
- dep->qflgs |= ERTS_DE_QFLG_BUSY;
- erts_smp_spin_unlock(&dep->qlock);
- de_busy = prt_busy = 1;
+ prt_busy = 1;
if (oq.first && !preempt)
goto finalize_only;
}
@@ -1907,22 +1889,23 @@ erts_dist_command(Port *prt, int reds_limit)
* dist entry in a non-busy state and resume suspended
* processes.
*/
- erts_smp_spin_lock(&dep->qlock);
+ erts_smp_mtx_lock(&dep->qlock);
ASSERT(dep->qsize >= obufsize);
dep->qsize -= obufsize;
obufsize = 0;
- if (de_busy && !prt_busy && dep->qsize < ERTS_DE_BUSY_LIMIT) {
+ if (!prt_busy
+ && (dep->qflgs & ERTS_DE_QFLG_BUSY)
+ && dep->qsize < erts_dist_buf_busy_limit) {
ErtsProcList *suspendees;
int resumed;
suspendees = get_suspended_on_de(dep, ERTS_DE_QFLG_BUSY);
- erts_smp_spin_unlock(&dep->qlock);
+ erts_smp_mtx_unlock(&dep->qlock);
resumed = erts_resume_processes(suspendees);
reds += resumed*ERTS_PORT_REDS_DIST_CMD_RESUMED;
- de_busy = 0;
}
else
- erts_smp_spin_unlock(&dep->qlock);
+ erts_smp_mtx_unlock(&dep->qlock);
}
ASSERT(!oq.first && !oq.last);
@@ -1931,10 +1914,10 @@ erts_dist_command(Port *prt, int reds_limit)
if (obufsize != 0) {
ASSERT(obufsize > 0);
- erts_smp_spin_lock(&dep->qlock);
+ erts_smp_mtx_lock(&dep->qlock);
ASSERT(dep->qsize >= obufsize);
dep->qsize -= obufsize;
- erts_smp_spin_unlock(&dep->qlock);
+ erts_smp_mtx_unlock(&dep->qlock);
}
ASSERT(foq.first || !foq.last);
@@ -1984,9 +1967,9 @@ erts_dist_command(Port *prt, int reds_limit)
foq.last = NULL;
#ifdef DEBUG
- erts_smp_spin_lock(&dep->qlock);
+ erts_smp_mtx_lock(&dep->qlock);
ASSERT(dep->qsize == obufsize);
- erts_smp_spin_unlock(&dep->qlock);
+ erts_smp_mtx_unlock(&dep->qlock);
#endif
}
else {
@@ -1995,14 +1978,14 @@ erts_dist_command(Port *prt, int reds_limit)
* Unhandle buffers need to be put back first
* in out_queue.
*/
- erts_smp_spin_lock(&dep->qlock);
+ erts_smp_mtx_lock(&dep->qlock);
dep->qsize -= obufsize;
obufsize = 0;
oq.last->next = dep->out_queue.first;
dep->out_queue.first = oq.first;
if (!dep->out_queue.last)
dep->out_queue.last = oq.last;
- erts_smp_spin_unlock(&dep->qlock);
+ erts_smp_mtx_unlock(&dep->qlock);
}
erts_schedule_dist_command(prt, NULL);
@@ -2026,10 +2009,10 @@ erts_kill_dist_connection(DistEntry *dep, Uint32 connection_id)
dep->status |= ERTS_DE_SFLG_EXITING;
- erts_smp_spin_lock(&dep->qlock);
+ erts_smp_mtx_lock(&dep->qlock);
ASSERT(!(dep->qflgs & ERTS_DE_QFLG_EXIT));
dep->qflgs |= ERTS_DE_QFLG_EXIT;
- erts_smp_spin_unlock(&dep->qlock);
+ erts_smp_mtx_unlock(&dep->qlock);
erts_schedule_dist_command(NULL, dep);
}
@@ -2400,13 +2383,13 @@ BIF_RETTYPE setnode_3(BIF_ALIST_3)
ErtsProcList *plp = erts_proclist_create(BIF_P);
plp->next = NULL;
erts_suspend(BIF_P, ERTS_PROC_LOCK_MAIN, NULL);
- erts_smp_spin_lock(&dep->qlock);
+ erts_smp_mtx_lock(&dep->qlock);
if (dep->suspended.last)
dep->suspended.last->next = plp;
else
dep->suspended.first = plp;
dep->suspended.last = plp;
- erts_smp_spin_unlock(&dep->qlock);
+ erts_smp_mtx_unlock(&dep->qlock);
goto yield;
}
@@ -2434,9 +2417,9 @@ BIF_RETTYPE setnode_3(BIF_ALIST_3)
ASSERT(dep->send);
#ifdef DEBUG
- erts_smp_spin_lock(&dep->qlock);
+ erts_smp_mtx_lock(&dep->qlock);
ASSERT(dep->qsize == 0);
- erts_smp_spin_unlock(&dep->qlock);
+ erts_smp_mtx_unlock(&dep->qlock);
#endif
erts_set_dist_entry_connected(dep, BIF_ARG_2, flags);
diff --git a/erts/emulator/beam/dist.h b/erts/emulator/beam/dist.h
index fa19c7fb45..64caf34550 100644
--- a/erts/emulator/beam/dist.h
+++ b/erts/emulator/beam/dist.h
@@ -99,7 +99,8 @@ typedef struct {
#define ERTS_DE_IS_CONNECTED(DEP) \
(!ERTS_DE_IS_NOT_CONNECTED((DEP)))
-
+#define ERTS_DE_BUSY_LIMIT (1024*1024)
+extern int erts_dist_buf_busy_limit;
extern int erts_is_alive;
/*
@@ -153,10 +154,10 @@ erts_dsig_prepare(ErtsDSigData *dsdp,
}
if (no_suspend) {
failure = ERTS_DSIG_PREP_CONNECTED;
- erts_smp_spin_lock(&dep->qlock);
+ erts_smp_mtx_lock(&dep->qlock);
if (dep->qflgs & ERTS_DE_QFLG_BUSY)
failure = ERTS_DSIG_PREP_WOULD_SUSPEND;
- erts_smp_spin_unlock(&dep->qlock);
+ erts_smp_mtx_unlock(&dep->qlock);
if (failure == ERTS_DSIG_PREP_WOULD_SUSPEND)
goto fail;
}
diff --git a/erts/emulator/beam/elib_malloc.c b/erts/emulator/beam/elib_malloc.c
deleted file mode 100644
index b18c48d8d6..0000000000
--- a/erts/emulator/beam/elib_malloc.c
+++ /dev/null
@@ -1,2334 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1997-2009. All Rights Reserved.
- *
- * The contents of this file are subject to the Erlang Public License,
- * Version 1.1, (the "License"); you may not use this file except in
- * compliance with the License. You should have received a copy of the
- * Erlang Public License along with this software. If not, it can be
- * retrieved online at http://www.erlang.org/.
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * %CopyrightEnd%
- */
-
-/*
-** Description: Faster malloc().
-*/
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "sys.h"
-
-#ifdef ENABLE_ELIB_MALLOC
-
-#undef THREAD_SAFE_ELIB_MALLOC
-#ifdef USE_THREADS
-#define THREAD_SAFE_ELIB_MALLOC 1
-#else
-#define THREAD_SAFE_ELIB_MALLOC 0
-#endif
-
-#include "erl_driver.h"
-#include "erl_threads.h"
-#include "elib_stat.h"
-#include <stdio.h>
-#include <stdlib.h>
-
-/* To avoid clobbering of names becaure of reclaim on VxWorks,
- we undefine all possible malloc, calloc etc. */
-#undef malloc
-#undef calloc
-#undef free
-#undef realloc
-
-#define ELIB_INLINE /* inline all possible functions */
-
-#ifndef ELIB_ALIGN
-#define ELIB_ALIGN sizeof(double)
-#endif
-
-#ifndef ELIB_HEAP_SIZE
-#define ELIB_HEAP_SIZE (64*1024) /* Default 64K */
-#endif
-
-#ifndef ELIB_HEAP_INCREAMENT
-#define ELIB_HEAP_INCREAMENT (32*1024) /* Default 32K */
-#endif
-
-#ifndef ELIB_FAILURE
-#define ELIB_FAILURE abort()
-#endif
-
-#undef ASSERT
-#ifdef DEBUG
-#define ASSERT(B) \
- ((void) ((B) ? 1 : (fprintf(stderr, "%s:%d: Assertion failed: %s\n", \
- __FILE__, __LINE__, #B), abort(), 0)))
-#else
-#define ASSERT(B) ((void) 1)
-#endif
-
-#ifndef USE_RECURSIVE_MALLOC_MUTEX
-#define USE_RECURSIVE_MALLOC_MUTEX 0
-#endif
-
-#if USE_RECURSIVE_MALLOC_MUTEX
-static erts_mtx_t malloc_mutex = ERTS_REC_MTX_INITER;
-#else /* #if USE_RECURSIVE_MALLOC_MUTEX */
-static erts_mtx_t malloc_mutex = ERTS_MTX_INITER;
-#if THREAD_SAFE_ELIB_MALLOC
-static erts_cnd_t malloc_cond = ERTS_CND_INITER;
-#endif
-#endif /* #if USE_RECURSIVE_MALLOC_MUTEX */
-
-typedef unsigned long EWord; /* Assume 32-bit in this implementation */
-typedef unsigned short EHalfWord; /* Assume 16-bit in this implementation */
-typedef unsigned char EByte; /* Assume 8-bit byte */
-
-
-#define elib_printf fprintf
-#define elib_putc fputc
-
-
-#if defined(__STDC__) || defined(__WIN32__)
-#define CONCAT(x,y) x##y
-#else
-#define CONCAT(x,y) x/**/y
-#endif
-
-
-#ifdef ELIB_DEBUG
-#define ELIB_PREFIX(fun, args) CONCAT(elib__,fun) args
-#else
-#define ELIB_PREFIX(fun, args) CONCAT(elib_,fun) args
-#endif
-
-#if defined(__STDC__)
-void *ELIB_PREFIX(malloc, (size_t));
-void *ELIB_PREFIX(calloc, (size_t, size_t));
-void ELIB_PREFIX(cfree, (EWord *));
-void ELIB_PREFIX(free, (EWord *));
-void *ELIB_PREFIX(realloc, (EWord *, size_t));
-void* ELIB_PREFIX(memresize, (EWord *, int));
-void* ELIB_PREFIX(memalign, (int, int));
-void* ELIB_PREFIX(valloc, (int));
-void* ELIB_PREFIX(pvalloc, (int));
-int ELIB_PREFIX(memsize, (EWord *));
-/* Extern interfaces used by VxWorks */
-size_t elib_sizeof(void *);
-void elib_init(EWord *, EWord);
-void elib_force_init(EWord *, EWord);
-#endif
-
-#if defined(__STDC__)
-/* define prototypes for missing */
-void* memalign(size_t a, size_t s);
-void* pvalloc(size_t nb);
-void* memresize(void *p, int nb);
-int memsize(void *p);
-#endif
-
-/* bytes to pages */
-#define PAGES(x) (((x)+page_size-1) / page_size)
-#define PAGE_ALIGN(p) ((char*)((((EWord)(p))+page_size-1)&~(page_size-1)))
-
-/* bytes to words */
-#define WORDS(x) (((x)+sizeof(EWord)-1) / sizeof(EWord))
-
-/* Align an address */
-#define ALIGN(p) ((EWord*)((((EWord)(p)+ELIB_ALIGN-1)&~(ELIB_ALIGN-1))))
-
-/* Calculate the size needed to keep alignment */
-
-#define ALIGN_BSZ(nb) ((nb+sizeof(EWord)+ELIB_ALIGN-1) & ~(ELIB_ALIGN-1))
-
-#define ALIGN_WSZ(nb) WORDS(ALIGN_BSZ(nb))
-
-#define ALIGN_SIZE(nb) (ALIGN_WSZ(nb) - 1)
-
-
-/* PARAMETERS */
-
-#if defined(ELIB_HEAP_SBRK)
-
-#undef PAGE_SIZE
-
-/* Get the system page size (NEED MORE DEFINES HERE) */
-#ifdef _SC_PAGESIZE
-#define PAGE_SIZE sysconf(_SC_PAGESIZE)
-#elif defined(_MSC_VER)
-# ifdef _M_ALPHA
-# define PAGE_SIZE 0x2000
-# else
-# define PAGE_SIZE 0x1000
-# endif
-#else
-#define PAGE_SIZE getpagesize()
-#endif
-
-#define ELIB_EXPAND(need) expand_sbrk(need)
-static FUNCTION(int, expand_sbrk, (EWord));
-
-#elif defined(ELIB_HEAP_FIXED)
-
-#define PAGE_SIZE 1024
-#define ELIB_EXPAND(need) -1
-static EWord fix_heap[WORDS(ELIB_HEAP_SIZE)];
-
-#elif defined(ELIB_HEAP_USER)
-
-#define PAGE_SIZE 1024
-#define ELIB_EXPAND(need) -1
-
-#else
-
-#error "ELIB HEAP TYPE NOT SET"
-
-#endif
-
-
-#define STAT_ALLOCED_BLOCK(SZ) \
-do { \
- tot_allocated += (SZ); \
- if (max_allocated < tot_allocated) \
- max_allocated = tot_allocated; \
-} while (0)
-
-#define STAT_FREED_BLOCK(SZ) \
-do { \
- tot_allocated -= (SZ); \
-} while (0)
-
-static int max_allocated = 0;
-static int tot_allocated = 0;
-static EWord* eheap; /* Align heap start */
-static EWord* eheap_top; /* Point to end of heap */
-EWord page_size = 0; /* Set by elib_init */
-
-#if defined(ELIB_DEBUG) || defined(DEBUG)
-#define ALIGN_CHECK(a, p) \
- do { \
- if ((EWord)(p) & (a-1)) { \
- elib_printf(stderr, \
- "RUNTIME ERROR: bad alignment (0x%lx:%d:%d)\n", \
- (unsigned long) (p), (int) a, __LINE__); \
- ELIB_FAILURE; \
- } \
- } while(0)
-#define ELIB_ALIGN_CHECK(p) ALIGN_CHECK(ELIB_ALIGN, p)
-#else
-#define ALIGN_CHECK(a, p)
-#define ELIB_ALIGN_CHECK(p)
-#endif
-
-#define DYNAMIC 32
-
-/*
-** Free block layout
-** 1 1 30
-** +--------------------------+
-** |F|P| Size |
-** +--------------------------+
-**
-** Where F is the free bit
-** P is the free above bit
-** Size is messured in words and does not include the hdr word
-**
-** If block is on the free list the size is also stored last in the block.
-**
-*/
-typedef struct _free_block FreeBlock;
-struct _free_block {
- EWord hdr;
- Uint flags;
- FreeBlock* parent;
- FreeBlock* left;
- FreeBlock* right;
- EWord v[1];
-};
-
-typedef struct _allocated_block {
- EWord hdr;
- EWord v[5];
-} AllocatedBlock;
-
-
-/*
- * Interface to tree routines.
- */
-typedef Uint Block_t;
-
-static Block_t* get_free_block(Uint);
-static void link_free_block(Block_t *);
-static void unlink_free_block(Block_t *del);
-
-#define FREE_BIT 0x80000000
-#define FREE_ABOVE_BIT 0x40000000
-#define SIZE_MASK 0x3fffffff /* 2^30 words = 2^32 bytes */
-
-/* Work on both FreeBlock and AllocatedBlock */
-#define SIZEOF(p) ((p)->hdr & SIZE_MASK)
-#define IS_FREE(p) (((p)->hdr & FREE_BIT) != 0)
-#define IS_FREE_ABOVE(p) (((p)->hdr & FREE_ABOVE_BIT) != 0)
-
-/* Given that we have a free block above find its size */
-#define SIZEOF_ABOVE(p) *(((EWord*) (p)) - 1)
-
-#define MIN_BLOCK_SIZE (sizeof(FreeBlock)/sizeof(EWord))
-#define MIN_WORD_SIZE (MIN_BLOCK_SIZE-1)
-#define MIN_BYTE_SIZE (sizeof(FreeBlock)-sizeof(EWord))
-
-#define MIN_ALIGN_SIZE ALIGN_SIZE(MIN_BYTE_SIZE)
-
-
-static AllocatedBlock* heap_head = 0;
-static AllocatedBlock* heap_tail = 0;
-static EWord eheap_size = 0;
-
-static int heap_locked;
-
-static int elib_need_init = 1;
-#if THREAD_SAFE_ELIB_MALLOC
-static int elib_is_initing = 0;
-#endif
-
-typedef FreeBlock RBTree_t;
-
-static RBTree_t* root = NULL;
-
-
-static FUNCTION(void, deallocate, (AllocatedBlock*, int));
-
-/*
- * Unlink a free block
- */
-
-#define mark_allocated(p, szp) do { \
- (p)->hdr = ((p)->hdr & FREE_ABOVE_BIT) | (szp); \
- (p)->v[szp] &= ~FREE_ABOVE_BIT; \
- } while(0)
-
-#define mark_free(p, szp) do { \
- (p)->hdr = FREE_BIT | (szp); \
- ((FreeBlock *)p)->v[szp-sizeof(FreeBlock)/sizeof(EWord)+1] = (szp); \
- } while(0)
-
-#if 0
-/* Help macros to log2 */
-#define LOG_1(x) (((x) > 1) ? 1 : 0)
-#define LOG_2(x) (((x) > 3) ? 2+LOG_1((x) >> 2) : LOG_1(x))
-#define LOG_4(x) (((x) > 15) ? 4+LOG_2((x) >> 4) : LOG_2(x))
-#define LOG_8(x) (((x) > 255) ? 8+LOG_4((x)>>8) : LOG_4(x))
-#define LOG_16(x) (((x) > 65535) ? 16+LOG_8((x)>>16) : LOG_8(x))
-
-#define log2(x) LOG_16(x)
-#endif
-
-/*
- * Split a block to be allocated.
- * Mark block as ALLOCATED and clear
- * FREE_ABOVE_BIT on next block
- *
- * nw is SIZE aligned and szp is SIZE aligned + 1
- */
-static void
-split_block(FreeBlock* p, EWord nw, EWord szp)
-{
- EWord szq;
- FreeBlock* q;
-
- szq = szp - nw;
- /* Preserve FREE_ABOVE bit in p->hdr !!! */
-
- if (szq >= MIN_ALIGN_SIZE+1) {
- szq--;
- p->hdr = (p->hdr & FREE_ABOVE_BIT) | nw;
-
- q = (FreeBlock*) (((EWord*) p) + nw + 1);
- mark_free(q, szq);
- link_free_block((Block_t *) q);
-
- q = (FreeBlock*) (((EWord*) q) + szq + 1);
- q->hdr |= FREE_ABOVE_BIT;
- }
- else {
- mark_allocated((AllocatedBlock*)p, szp);
- }
-}
-
-/*
- * Find a free block
- */
-static FreeBlock*
-alloc_block(EWord nw)
-{
- for (;;) {
- FreeBlock* p = (FreeBlock *) get_free_block(nw);
-
- if (p != NULL) {
- return p;
- } else if (ELIB_EXPAND(nw+MIN_WORD_SIZE)) {
- return 0;
- }
- }
-}
-
-
-size_t elib_sizeof(void *p)
-{
- AllocatedBlock* pp;
-
- if (p != 0) {
- pp = (AllocatedBlock*) (((char *)p)-1);
- return SIZEOF(pp);
- }
- return 0;
-}
-
-static void locked_elib_init(EWord*, EWord);
-static void init_elib_malloc(EWord*, EWord);
-
-/*
-** Initialize the elib
-** The addr and sz is only used when compiled with EXPAND_ADDR
-*/
-/* Not static, this is used by VxWorks */
-void elib_init(EWord* addr, EWord sz)
-{
- if (!elib_need_init)
- return;
- erts_mtx_lock(&malloc_mutex);
- locked_elib_init(addr, sz);
- erts_mtx_unlock(&malloc_mutex);
-}
-
-static void locked_elib_init(EWord* addr, EWord sz)
-{
- if (!elib_need_init)
- return;
-
-#if THREAD_SAFE_ELIB_MALLOC
-
-#if !USE_RECURSIVE_MALLOC_MUTEX
- {
- static erts_tid_t initer_tid;
-
- if(elib_is_initing) {
-
- if(erts_equal_tids(initer_tid, erts_thr_self()))
- return;
-
- /* Wait until initializing thread is done with initialization */
-
- while(elib_need_init)
- erts_cnd_wait(&malloc_cond, &malloc_mutex);
-
- return;
- }
- else {
- initer_tid = erts_thr_self();
- elib_is_initing = 1;
- }
- }
-#else
- if(elib_is_initing)
- return;
- elib_is_initing = 1;
-#endif
-
-#endif /* #if THREAD_SAFE_ELIB_MALLOC */
-
- /* Do the actual initialization of the malloc implementation */
- init_elib_malloc(addr, sz);
-
-#if THREAD_SAFE_ELIB_MALLOC
-
-#if !USE_RECURSIVE_MALLOC_MUTEX
- erts_mtx_unlock(&malloc_mutex);
-#endif
-
- /* Recursive calls to malloc are allowed here... */
- erts_mtx_set_forksafe(&malloc_mutex);
-
-#if !USE_RECURSIVE_MALLOC_MUTEX
- erts_mtx_lock(&malloc_mutex);
- elib_is_initing = 0;
-#endif
-
-#endif /* #if THREAD_SAFE_ELIB_MALLOC */
-
- elib_need_init = 0;
-
-#if THREAD_SAFE_ELIB_MALLOC && !USE_RECURSIVE_MALLOC_MUTEX
- erts_cnd_broadcast(&malloc_cond);
-#endif
-
-}
-
-static void init_elib_malloc(EWord* addr, EWord sz)
-{
- int i;
- FreeBlock* freep;
- EWord tmp_sz;
-#ifdef ELIB_HEAP_SBRK
- char* top;
- EWord n;
-#endif
-
- max_allocated = 0;
- tot_allocated = 0;
- root = NULL;
-
- /* Get the page size (may involve system call!!!) */
- page_size = PAGE_SIZE;
-
-#if defined(ELIB_HEAP_SBRK)
- sz = PAGES(ELIB_HEAP_SIZE)*page_size;
-
- if ((top = (char*) sbrk(0)) == (char*)-1) {
- elib_printf(stderr, "could not initialize elib, sbrk(0)");
- ELIB_FAILURE;
- }
- n = PAGE_ALIGN(top) - top;
- if ((top = (char*) sbrk(n)) == (char*)-1) {
- elib_printf(stderr, "could not initialize elib, sbrk(n)");
- ELIB_FAILURE;
- }
- if ((eheap = (EWord*) sbrk(sz)) == (EWord*)-1) {
- elib_printf(stderr, "could not initialize elib, sbrk(SIZE)");
- ELIB_FAILURE;
- }
- sz = WORDS(ELIB_HEAP_SIZE);
-#elif defined(ELIB_HEAP_FIXED)
- eheap = fix_heap;
- sz = WORDS(ELIB_HEAP_SIZE);
-#elif defined(ELIB_HEAP_USER)
- eheap = addr;
- sz = WORDS(sz);
-#else
- return -1;
-#endif
- eheap_size = 0;
-
- /* Make sure that the first word of the heap_head is aligned */
- addr = ALIGN(eheap+1);
- sz -= ((addr - 1) - eheap); /* Subtract unusable size */
- eheap_top = eheap = addr - 1; /* Set new aligned heap start */
-
- eheap_top[sz-1] = 0; /* Heap stop mark */
-
- addr = eheap;
- heap_head = (AllocatedBlock*) addr;
- heap_head->hdr = MIN_ALIGN_SIZE;
- for (i = 0; i < MIN_ALIGN_SIZE; i++)
- heap_head->v[i] = 0;
-
- addr += (MIN_ALIGN_SIZE+1);
- freep = (FreeBlock*) addr;
- tmp_sz = sz - (((MIN_ALIGN_SIZE+1) + MIN_BLOCK_SIZE) + 1 + 1);
- mark_free(freep, tmp_sz);
- link_free_block((Block_t *) freep);
-
- /* No need to align heap tail */
- heap_tail = (AllocatedBlock*) &eheap_top[sz-MIN_BLOCK_SIZE-1];
- heap_tail->hdr = FREE_ABOVE_BIT | MIN_WORD_SIZE;
- heap_tail->v[0] = 0;
- heap_tail->v[1] = 0;
- heap_tail->v[2] = 0;
-
- eheap_top += sz;
- eheap_size += sz;
-
- heap_locked = 0;
-}
-
-#ifdef ELIB_HEAP_USER
-void elib_force_init(EWord* addr, EWord sz)
-{
- elib_need_init = 1;
- elib_init(addr,sz);
-}
-#endif
-
-#ifdef ELIB_HEAP_SBRK
-
-/*
-** need in number of words (should include head and tail words)
-*/
-static int expand_sbrk(EWord sz)
-{
- EWord* p;
- EWord bytes = sz * sizeof(EWord);
- EWord size;
- AllocatedBlock* tail;
-
- if (bytes < ELIB_HEAP_SIZE)
- size = PAGES(ELIB_HEAP_INCREAMENT)*page_size;
- else
- size = PAGES(bytes)*page_size;
-
- if ((p = (EWord*) sbrk(size)) == ((EWord*) -1))
- return -1;
-
- if (p != eheap_top) {
- elib_printf(stderr, "panic: sbrk moved\n");
- ELIB_FAILURE;
- }
-
- sz = WORDS(size);
-
- /* Set new endof heap marker and a new heap tail */
- eheap_top[sz-1] = 0;
-
- tail = (AllocatedBlock*) &eheap_top[sz-MIN_BLOCK_SIZE-1];
- tail->hdr = FREE_ABOVE_BIT | MIN_WORD_SIZE;
- tail->v[0] = 0;
- tail->v[1] = 0;
- tail->v[2] = 0;
-
- /* Patch old tail with new appended size */
- heap_tail->hdr = (heap_tail->hdr & FREE_ABOVE_BIT) |
- (MIN_WORD_SIZE+1+(sz-MIN_BLOCK_SIZE-1));
- deallocate(heap_tail, 0);
-
- heap_tail = tail;
-
- eheap_size += sz;
- eheap_top += sz;
-
- return 0;
-}
-
-#endif /* ELIB_HEAP_SBRK */
-
-
-/*
-** Scan heap and check for corrupted heap
-*/
-int elib_check_heap(void)
-{
- AllocatedBlock* p = heap_head;
- EWord sz;
-
- if (heap_locked) {
- elib_printf(stderr, "heap is locked no info avaiable\n");
- return 0;
- }
-
- while((sz = SIZEOF(p)) != 0) {
- if (IS_FREE(p)) {
- if (p->v[sz-1] != sz) {
- elib_printf(stderr, "panic: heap corrupted\r\n");
- ELIB_FAILURE;
- }
- p = (AllocatedBlock*) (p->v + sz);
- if (!IS_FREE_ABOVE(p)) {
- elib_printf(stderr, "panic: heap corrupted\r\n");
- ELIB_FAILURE;
- }
- }
- else
- p = (AllocatedBlock*) (p->v + sz);
- }
- return 1;
-}
-
-/*
-** Load the byte vector pointed to by v of length vsz
-** with a heap image
-** The scale is defined by vsz and the current heap size
-** free = 0, full = 255
-**
-**
-*/
-int elib_heap_map(EByte* v, int vsz)
-{
- AllocatedBlock* p = heap_head;
- EWord sz;
- int gsz = eheap_size / vsz; /* The granuality used */
- int fsz = 0;
- int usz = 0;
-
- if (gsz == 0)
- return -1; /* too good reolution */
-
- while((sz = SIZEOF(p)) != 0) {
- if (IS_FREE(p)) {
- fsz += sz;
- if ((fsz + usz) > gsz) {
- *v++ = (255*usz)/gsz;
- fsz -= (gsz - usz);
- usz = 0;
- while(fsz >= gsz) {
- *v++ = 0;
- fsz -= gsz;
- }
- }
- }
- else {
- usz += sz;
- if ((fsz + usz) > gsz) {
- *v++ = 255 - (255*fsz)/gsz;
- usz -= (gsz - fsz);
- fsz = 0;
- while(usz >= gsz) {
- *v++ = 255;
- usz -= gsz;
- }
- }
- }
- p = (AllocatedBlock*) (p->v + sz);
- }
- return 0;
-}
-
-/*
-** Generate a histogram of free/allocated blocks
-** Count granuality of 10 gives
-** (0-10],(10-100],(100-1000],(1000-10000] ...
-** (0-2], (2-4], (4-8], (8-16], ....
-*/
-static int i_logb(EWord size, int base)
-{
- int lg = 0;
- while(size >= base) {
- size /= base;
- lg++;
- }
- return lg;
-}
-
-int elib_histo(EWord* vf, EWord* va, int vsz, int base)
-{
- AllocatedBlock* p = heap_head;
- EWord sz;
- int i;
- int linear;
-
- if ((vsz <= 1) || (vf == 0 && va == 0))
- return -1;
-
- if (base < 0) {
- linear = 1;
- base = -base;
- }
- else
- linear = 0;
-
- if (base <= 1)
- return -1;
-
- if (vf != 0) {
- for (i = 0; i < vsz; i++)
- vf[i] = 0;
- }
- if (va != 0) {
- for (i = 0; i < vsz; i++)
- va[i] = 0;
- }
-
- while((sz = SIZEOF(p)) != 0) {
- if (IS_FREE(p)) {
- if (vf != 0) {
- int val;
- if (linear)
- val = sz / base;
- else
- val = i_logb(sz, base);
- if (val >= vsz)
- vf[vsz-1]++;
- else
- vf[val]++;
- }
- }
- else {
- if (va != 0) {
- int val;
- if (linear)
- val = sz / base;
- else
- val = i_logb(sz, base);
- if (val >= vsz)
- va[vsz-1]++;
- else
- va[val]++;
- }
- }
- p = (AllocatedBlock*) (p->v + sz);
- }
- return 0;
-}
-
-/*
-** Fill the info structure with actual values
-** Total
-** Allocated
-** Free
-** maxMaxFree
-*/
-void elib_stat(struct elib_stat* info)
-{
- EWord blks = 0;
- EWord sz_free = 0;
- EWord sz_alloc = 0;
- EWord sz_max_free = 0;
- EWord sz_min_used = 0x7fffffff;
- EWord sz;
- EWord num_free = 0;
- AllocatedBlock* p = heap_head;
-
- info->mem_total = eheap_size;
-
- p = (AllocatedBlock*) (p->v + SIZEOF(p));
-
- while((sz = SIZEOF(p)) != 0) {
- blks++;
- if (IS_FREE(p)) {
- if (sz > sz_max_free)
- sz_max_free = sz;
- sz_free += sz;
- ++num_free;
- }
- else {
- if (sz < sz_min_used)
- sz_min_used = sz;
- sz_alloc += sz;
- }
- p = (AllocatedBlock*) (p->v + sz);
- }
- info->mem_blocks = blks;
- info->free_blocks = num_free;
- info->mem_alloc = sz_alloc;
- info->mem_free = sz_free;
- info->min_used = sz_min_used;
- info->max_free = sz_max_free;
- info->mem_max_alloc = max_allocated;
- ASSERT(sz_alloc == tot_allocated);
-}
-
-/*
-** Dump the heap
-*/
-void elib_heap_dump(char* label)
-{
- AllocatedBlock* p = heap_head;
- EWord sz;
-
- elib_printf(stderr, "HEAP DUMP (%s)\n", label);
- if (!elib_check_heap())
- return;
-
- while((sz = SIZEOF(p)) != 0) {
- if (IS_FREE(p)) {
- elib_printf(stderr, "%p: FREE, size = %d\n", p, (int) sz);
- }
- else {
- elib_printf(stderr, "%p: USED, size = %d %s\n", p, (int) sz,
- IS_FREE_ABOVE(p)?"(FREE ABOVE)":"");
- }
- p = (AllocatedBlock*) (p->v + sz);
- }
-}
-
-/*
-** Scan heaps and count:
-** free_size, allocated_size, max_free_block
-*/
-void elib_statistics(void* to)
-{
- struct elib_stat info;
- EWord frag;
-
- if (!elib_check_heap())
- return;
-
- elib_stat(&info);
-
- frag = 1000 - ((1000 * info.max_free) / info.mem_free);
-
- elib_printf(to, "Heap Statistics: total(%d), blocks(%d), frag(%d.%d%%)\n",
- info.mem_total, info.mem_blocks,
- (int) frag/10, (int) frag % 10);
-
- elib_printf(to, " allocated(%d), free(%d), "
- "free_blocks(%d)\n",
- info.mem_alloc, info.mem_free,info.free_blocks);
- elib_printf(to, " max_free(%d), min_used(%d)\n",
- info.max_free, info.min_used);
-}
-
-/*
-** Allocate a least nb bytes with alignment a
-** Algorithm:
-** 1) Try locate a block which match exacly among the by direct index.
-** 2) Try using a fix block of greater size
-** 3) Try locate a block by searching in lists where block sizes
-** X may vary between 2^i < X <= 2^(i+1)
-**
-** Reset memory to zero if clear is true
-*/
-static AllocatedBlock* allocate(EWord nb, EWord a, int clear)
-{
- FreeBlock* p;
- EWord nw;
-
- if (a == ELIB_ALIGN) {
- /*
- * Common case: Called by malloc(), realloc(), calloc().
- */
- nw = nb < MIN_BYTE_SIZE ? MIN_ALIGN_SIZE : ALIGN_SIZE(nb);
-
- if ((p = alloc_block(nw)) == 0)
- return NULL;
- } else {
- /*
- * Special case: Called by memalign().
- */
- EWord asz, szp, szq, tmpsz;
- FreeBlock *q;
-
- if ((p = alloc_block((1+MIN_ALIGN_SIZE)*sizeof(EWord)+a-1+nb)) == 0)
- return NULL;
-
- asz = a - ((EWord) ((AllocatedBlock *)p)->v) % a;
-
- if (asz != a) {
- /* Enforce the alignment requirement by cutting of a free
- block at the beginning of the block. */
-
- if (asz < (1+MIN_ALIGN_SIZE)*sizeof(EWord) && !IS_FREE_ABOVE(p)) {
- /* Not enough room to cut of a free block;
- increase align size */
- asz += (((1+MIN_ALIGN_SIZE)*sizeof(EWord) + a - 1)/a)*a;
- }
-
- szq = ALIGN_SIZE(asz - sizeof(EWord));
- szp = SIZEOF(p) - szq - 1;
-
- q = p;
- p = (FreeBlock*) (((EWord*) q) + szq + 1);
- p->hdr = FREE_ABOVE_BIT | FREE_BIT | szp;
-
- if (IS_FREE_ABOVE(q)) { /* This should not be possible I think,
- but just in case... */
- tmpsz = SIZEOF_ABOVE(q) + 1;
- szq += tmpsz;
- q = (FreeBlock*) (((EWord*) q) - tmpsz);
- unlink_free_block((Block_t *) q);
- q->hdr = (q->hdr & FREE_ABOVE_BIT) | FREE_BIT | szq;
- }
- mark_free(q, szq);
- link_free_block((Block_t *) q);
-
- } /* else already had the correct alignment */
-
- nw = nb < MIN_BYTE_SIZE ? MIN_ALIGN_SIZE : ALIGN_SIZE(nb);
- }
-
- split_block(p, nw, SIZEOF(p));
-
- STAT_ALLOCED_BLOCK(SIZEOF(p));
-
- if (clear) {
- EWord* pp = ((AllocatedBlock*)p)->v;
-
- while(nw--)
- *pp++ = 0;
- }
-
- return (AllocatedBlock*) p;
-}
-
-
-/*
-** Deallocate memory pointed to by p
-** 1. Merge with block above if this block is free
-** 2. Merge with block below if this block is free
-** Link the block to the correct free list
-**
-** p points to the block header!
-**
-*/
-static void deallocate(AllocatedBlock* p, int stat_count)
-{
- FreeBlock* q;
- EWord szq;
- EWord szp;
-
- szp = SIZEOF(p);
-
- if (stat_count)
- STAT_FREED_BLOCK(SIZEOF(p));
-
- if (IS_FREE_ABOVE(p)) {
- szq = SIZEOF_ABOVE(p);
- q = (FreeBlock*) ( ((EWord*) p) - szq - 1);
- unlink_free_block((Block_t *) q);
-
- p = (AllocatedBlock*) q;
- szp += (szq + 1);
- }
- q = (FreeBlock*) (p->v + szp);
- if (IS_FREE(q)) {
- szq = SIZEOF(q);
- unlink_free_block((Block_t *) q);
- szp += (szq + 1);
- }
- else
- q->hdr |= FREE_ABOVE_BIT;
-
- /* The block above p can NEVER be free !!! */
- p->hdr = FREE_BIT | szp;
- p->v[szp-1] = szp;
-
- link_free_block((Block_t *) p);
-}
-
-/*
-** Reallocate memory
-** If preserve is true then data is moved if neccesary
-*/
-static AllocatedBlock* reallocate(AllocatedBlock* p, EWord nb, int preserve)
-{
- EWord szp;
- EWord szq;
- EWord sz;
- EWord nw;
- FreeBlock* q;
-
- if (nb < MIN_BYTE_SIZE)
- nw = MIN_ALIGN_SIZE;
- else
- nw = ALIGN_SIZE(nb);
-
- sz = szp = SIZEOF(p);
-
- STAT_FREED_BLOCK(szp);
-
- /* Merge with block below */
- q = (FreeBlock*) (p->v + szp);
- if (IS_FREE(q)) {
- szq = SIZEOF(q);
- unlink_free_block((Block_t *) q);
- szp += (szq + 1);
- }
-
- if (nw <= szp) {
- split_block((FreeBlock *) p, nw, szp);
- STAT_ALLOCED_BLOCK(SIZEOF(p));
- return p;
- }
- else {
- EWord* dp = p->v;
- AllocatedBlock* npp;
-
- if (IS_FREE_ABOVE(p)) {
- szq = SIZEOF_ABOVE(p);
- if (szq + szp + 1 >= nw) {
- q = (FreeBlock*) (((EWord*) p) - szq - 1);
- unlink_free_block((Block_t * )q);
- szp += (szq + 1);
- p = (AllocatedBlock*) q;
-
- if (preserve) {
- EWord* pp = p->v;
- while(sz--)
- *pp++ = *dp++;
- }
- split_block((FreeBlock *) p, nw, szp);
- STAT_ALLOCED_BLOCK(SIZEOF(p));
- return p;
- }
- }
-
- /*
- * Update p so that allocate() and deallocate() works.
- * (Note that allocate() may call expand_sbrk(), which in
- * in turn calls deallocate().)
- */
-
- p->hdr = (p->hdr & FREE_ABOVE_BIT) | szp;
- p->v[szp] &= ~FREE_ABOVE_BIT;
-
- npp = allocate(nb, ELIB_ALIGN, 0);
- if(npp == NULL)
- return NULL;
- if (preserve) {
- EWord* pp = npp->v;
- while(sz--)
- *pp++ = *dp++;
- }
- deallocate(p, 0);
- return npp;
- }
-}
-
-/*
-** What malloc() and friends should do (and return) when the heap is
-** exhausted. [sverkerw]
-*/
-static void* heap_exhausted(void)
-{
- /* Choose behaviour */
-#if 0
- /* Crash-and-burn --- leave a usable corpse (hopefully) */
- abort();
-#endif
- /* The usual ANSI-compliant behaviour */
- return NULL;
-}
-
-/*
-** Allocate size bytes of memory
-*/
-void* ELIB_PREFIX(malloc, (size_t nb))
-{
- void *res;
- AllocatedBlock* p;
-
- erts_mtx_lock(&malloc_mutex);
- if (elib_need_init)
- locked_elib_init(NULL,(EWord)0);
-
- if (nb == 0)
- res = NULL;
- else if ((p = allocate(nb, ELIB_ALIGN, 0)) != 0) {
- ELIB_ALIGN_CHECK(p->v);
- res = p->v;
- }
- else
- res = heap_exhausted();
-
- erts_mtx_unlock(&malloc_mutex);
-
- return res;
-}
-
-
-void* ELIB_PREFIX(calloc, (size_t nelem, size_t size))
-{
- void *res;
- int nb;
- AllocatedBlock* p;
-
- erts_mtx_lock(&malloc_mutex);
- if (elib_need_init)
- locked_elib_init(NULL,(EWord)0);
-
- if ((nb = nelem * size) == 0)
- res = NULL;
- else if ((p = allocate(nb, ELIB_ALIGN, 1)) != 0) {
- ELIB_ALIGN_CHECK(p->v);
- res = p->v;
- }
- else
- res = heap_exhausted();
-
- erts_mtx_unlock(&malloc_mutex);
-
- return res;
-}
-
-/*
-** Free memory allocated by malloc
-*/
-
-void ELIB_PREFIX(free, (EWord* p))
-{
- erts_mtx_lock(&malloc_mutex);
- if (elib_need_init)
- locked_elib_init(NULL,(EWord)0);
-
- if (p != 0)
- deallocate((AllocatedBlock*)(p-1), 1);
-
- erts_mtx_unlock(&malloc_mutex);
-}
-
-void ELIB_PREFIX(cfree, (EWord* p))
-{
- ELIB_PREFIX(free, (p));
-}
-
-
-/*
-** Realloc the memory allocated in p to nb number of bytes
-**
-*/
-
-void* ELIB_PREFIX(realloc, (EWord* p, size_t nb))
-{
- void *res = NULL;
- AllocatedBlock* pp;
-
- erts_mtx_lock(&malloc_mutex);
- if (elib_need_init)
- locked_elib_init(NULL,(EWord)0);
-
- if (p != 0) {
- pp = (AllocatedBlock*) (p-1);
- if (nb > 0) {
- if ((pp = reallocate(pp, nb, 1)) != 0) {
- ELIB_ALIGN_CHECK(pp->v);
- res = pp->v;
- }
- }
- else
- deallocate(pp, 1);
- }
- else if (nb > 0) {
- if ((pp = allocate(nb, ELIB_ALIGN, 0)) != 0) {
- ELIB_ALIGN_CHECK(pp->v);
- res = pp->v;
- }
- else
- res = heap_exhausted();
- }
-
- erts_mtx_unlock(&malloc_mutex);
-
- return res;
-}
-
-/*
-** Resize the memory area pointed to by p with nb number of bytes
-*/
-void* ELIB_PREFIX(memresize, (EWord* p, int nb))
-{
- void *res = NULL;
- AllocatedBlock* pp;
-
- erts_mtx_lock(&malloc_mutex);
- if (elib_need_init)
- locked_elib_init(NULL,(EWord)0);
-
- if (p != 0) {
- pp = (AllocatedBlock*) (p-1);
- if (nb > 0) {
- if ((pp = reallocate(pp, nb, 0)) != 0) {
- ELIB_ALIGN_CHECK(pp->v);
- res = pp->v;
- }
- }
- else
- deallocate(pp, 1);
- }
- else if (nb > 0) {
- if ((pp = allocate(nb, ELIB_ALIGN, 0)) != 0) {
- ELIB_ALIGN_CHECK(pp->v);
- res = pp->v;
- }
- else
- res = heap_exhausted();
- }
-
- erts_mtx_unlock(&malloc_mutex);
-
- return res;
-}
-
-
-/* Create aligned memory a must be a power of 2 !!! */
-
-void* ELIB_PREFIX(memalign, (int a, int nb))
-{
- void *res;
- AllocatedBlock* p;
-
- erts_mtx_lock(&malloc_mutex);
- if (elib_need_init)
- locked_elib_init(NULL,(EWord)0);
-
- if (nb == 0 || a <= 0)
- res = NULL;
- else if ((p = allocate(nb, a, 0)) != 0) {
- ALIGN_CHECK(a, p->v);
- res = p->v;
- }
- else
- res = heap_exhausted();
-
- erts_mtx_unlock(&malloc_mutex);
-
- return res;
-}
-
-void* ELIB_PREFIX(valloc, (int nb))
-{
- return ELIB_PREFIX(memalign, (page_size, nb));
-}
-
-
-void* ELIB_PREFIX(pvalloc, (int nb))
-{
- return ELIB_PREFIX(memalign, (page_size, PAGES(nb)*page_size));
-}
-/* Return memory size for pointer p in bytes */
-
-int ELIB_PREFIX(memsize, (p))
-EWord* p;
-{
- return SIZEOF((AllocatedBlock*)(p-1))*4;
-}
-
-
-/*
-** --------------------------------------------------------------------------
-** DEBUG LIBRARY
-** --------------------------------------------------------------------------
-*/
-
-#ifdef ELIB_DEBUG
-
-#define IN_HEAP(p) (((p) >= (char*) eheap) && (p) < (char*) eheap_top)
-/*
-** ptr_to_block: return the pointer to heap block pointed into by ptr
-** Returns 0 if not pointing into a block
-*/
-
-static EWord* ptr_to_block(char* ptr)
-{
- AllocatedBlock* p = heap_head;
- EWord sz;
-
- while((sz = SIZEOF(p)) != 0) {
- if ((ptr >= (char*) p->v) && (ptr < (char*)(p->v+sz)))
- return p->v;
- p = (AllocatedBlock*) (p->v + sz);
- }
- return 0;
-}
-
-/*
-** Validate a pointer
-** returns:
-** 0 - if points to start of a block
-** 1 - if points outsize heap
-** -1 - if points inside block
-**
-*/
-static int check_pointer(char* ptr)
-{
- if (IN_HEAP(ptr)) {
- if (ptr_to_block(ptr) == 0)
- return 1;
- return 0;
- }
- return -1;
-}
-
-/*
-** Validate a memory area
-** returns:
-** 0 - if area is included in a block
-** -1 - if area overlap a heap block
-** 1 - if area is outside heap
-*/
-static int check_area(char* ptr, int n)
-{
- if (IN_HEAP(ptr)) {
- if (IN_HEAP(ptr+n-1)) {
- EWord* p1 = ptr_to_block(ptr);
- EWord* p2 = ptr_to_block(ptr+n-1);
-
- if (p1 == p2)
- return (p1 == 0) ? -1 : 0;
- return -1;
- }
- }
- else if (IN_HEAP(ptr+n-1))
- return -1;
- return 1;
-}
-
-/*
-** Check if a block write will overwrite heap block
-*/
-static void check_write(char* ptr, int n, char* file, int line, char* fun)
-{
- if (check_area(ptr, n) == -1) {
- elib_printf(stderr, "RUNTIME ERROR: %s heap overwrite\n", fun);
- elib_printf(stderr, "File: %s Line: %d\n", file, line);
- ELIB_FAILURE;
- }
-}
-
-/*
-** Check if a pointer is an allocated object
-*/
-static void check_allocated_block(char* ptr, char* file, int line, char* fun)
-{
- EWord* q;
-
- if (!IN_HEAP(ptr) || ((q=ptr_to_block(ptr)) == 0) || (ptr != (char*) q)) {
- elib_printf(stderr, "RUNTIME ERROR: %s non heap pointer\n", fun);
- elib_printf(stderr, "File: %s Line: %d\n", file, line);
- ELIB_FAILURE;
- }
-
- if (IS_FREE((AllocatedBlock*)(q-1))) {
- elib_printf(stderr, "RUNTIME ERROR: %s free pointer\n", fun);
- elib_printf(stderr, "File: %s Line: %d\n", file, line);
- ELIB_FAILURE;
- }
-
-}
-
-/*
-** --------------------------------------------------------------------------
-** DEBUG VERSIONS (COMPILED WITH THE ELIB.H)
-** --------------------------------------------------------------------------
-*/
-
-void* elib_dbg_malloc(int n, char* file, int line)
-{
- return elib__malloc(n);
-}
-
-void* elib_dbg_calloc(int n, int s, char* file, int line)
-{
- return elib__calloc(n, s);
-}
-
-void* elib_dbg_realloc(EWord* p, int n, char* file, int line)
-{
- if (p == 0)
- return elib__malloc(n);
- check_allocated_block(p, file, line, "elib_realloc");
- return elib__realloc(p, n);
-}
-
-void elib_dbg_free(EWord* p, char* file, int line)
-{
- if (p == 0)
- return;
- check_allocated_block(p, file, line, "elib_free");
- elib__free(p);
-}
-
-void elib_dbg_cfree(EWord* p, char* file, int line)
-{
- if (p == 0)
- return;
- check_allocated_block(p, file, line, "elib_free");
- elib__cfree(p);
-}
-
-void* elib_dbg_memalign(int a, int n, char* file, int line)
-{
- return elib__memalign(a, n);
-}
-
-void* elib_dbg_valloc(int n, char* file, int line)
-{
- return elib__valloc(n);
-}
-
-void* elib_dbg_pvalloc(int n, char* file, int line)
-{
- return elib__pvalloc(n);
-}
-
-void* elib_dbg_memresize(EWord* p, int n, char* file, int line)
-{
- if (p == 0)
- return elib__malloc(n);
- check_allocated_block(p, file, line, "elib_memresize");
- return elib__memresize(p, n);
-}
-
-int elib_dbg_memsize(void* p, char* file, int line)
-{
- check_allocated_block(p, file, line, "elib_memsize");
- return elib__memsize(p);
-}
-
-/*
-** --------------------------------------------------------------------------
-** LINK TIME FUNCTIONS (NOT COMPILED CALLS)
-** --------------------------------------------------------------------------
-*/
-
-void* elib_malloc(int n)
-{
- return elib_dbg_malloc(n, "", -1);
-}
-
-void* elib_calloc(int n, int s)
-{
- return elib_dbg_calloc(n, s, "", -1);
-}
-
-void* elib_realloc(EWord* p, int n)
-{
- return elib_dbg_realloc(p, n, "", -1);
-}
-
-void elib_free(EWord* p)
-{
- elib_dbg_free(p, "", -1);
-}
-
-void elib_cfree(EWord* p)
-{
- elib_dbg_cfree(p, "", -1);
-}
-
-void* elib_memalign(int a, int n)
-{
- return elib_dbg_memalign(a, n, "", -1);
-}
-
-void* elib_valloc(int n)
-{
- return elib_dbg_valloc(n, "", -1);
-}
-
-void* elib_pvalloc(int n)
-{
- return elib_dbg_pvalloc(n, "", -1);
-}
-
-void* elib_memresize(EWord* p, int n)
-{
- return elib_dbg_memresize(p, n, "", -1);
-}
-
-
-int elib_memsize(EWord* p)
-{
- return elib_dbg_memsize(p, "", -1);
-}
-
-#endif /* ELIB_DEBUG */
-
-/*
-** --------------------------------------------------------------------------
-** Map c library functions to elib
-** --------------------------------------------------------------------------
-*/
-
-#if defined(ELIB_ALLOC_IS_CLIB)
-void* malloc(size_t nb)
-{
- return elib_malloc(nb);
-}
-
-void* calloc(size_t nelem, size_t size)
-{
- return elib_calloc(nelem, size);
-}
-
-
-void free(void *p)
-{
- elib_free(p);
-}
-
-void cfree(void *p)
-{
- elib_cfree(p);
-}
-
-void* realloc(void* p, size_t nb)
-{
- return elib_realloc(p, nb);
-}
-
-
-void* memalign(size_t a, size_t s)
-{
- return elib_memalign(a, s);
-}
-
-void* valloc(size_t nb)
-{
- return elib_valloc(nb);
-}
-
-void* pvalloc(size_t nb)
-{
- return elib_pvalloc(nb);
-}
-
-#if 0
-void* memresize(void* p, int nb)
-{
- return elib_memresize(p, nb);
-}
-
-int memsize(void* p)
-{
- return elib_memsize(p);
-}
-#endif
-#endif /* ELIB_ALLOC_IS_CLIB */
-
-#endif /* ENABLE_ELIB_MALLOC */
-
-void elib_ensure_initialized(void)
-{
-#ifdef ENABLE_ELIB_MALLOC
-#ifndef ELIB_DONT_INITIALIZE
- elib_init(NULL, 0);
-#endif
-#endif
-}
-
-#ifdef ENABLE_ELIB_MALLOC
-/**
- ** A Slightly modified version of the "address order best fit" algorithm
- ** used in erl_bestfit_alloc.c. Comments refer to that implementation.
- **/
-
-/*
- * Description: A combined "address order best fit"/"best fit" allocator
- * based on a Red-Black (binary search) Tree. The search,
- * insert, and delete operations are all O(log n) operations
- * on a Red-Black Tree. In the "address order best fit" case
- * n equals number of free blocks, and in the "best fit" case
- * n equals number of distinct sizes of free blocks. Red-Black
- * Trees are described in "Introduction to Algorithms", by
- * Thomas H. Cormen, Charles E. Leiserson, and
- * Ronald L. Riverest.
- *
- * This module is a callback-module for erl_alloc_util.c
- *
- * Author: Rickard Green
- */
-
-#ifdef DEBUG
-#if 0
-#define HARD_DEBUG
-#endif
-#else
-#undef HARD_DEBUG
-#endif
-
-#define SZ_MASK SIZE_MASK
-#define FLG_MASK (~(SZ_MASK))
-
-#define BLK_SZ(B) (*((Block_t *) (B)) & SZ_MASK)
-
-#define TREE_NODE_FLG (((Uint) 1) << 0)
-#define RED_FLG (((Uint) 1) << 1)
-#ifdef HARD_DEBUG
-# define LEFT_VISITED_FLG (((Uint) 1) << 2)
-# define RIGHT_VISITED_FLG (((Uint) 1) << 3)
-#endif
-
-#define IS_TREE_NODE(N) (((RBTree_t *) (N))->flags & TREE_NODE_FLG)
-#define IS_LIST_ELEM(N) (!IS_TREE_NODE(((RBTree_t *) (N))))
-
-#define SET_TREE_NODE(N) (((RBTree_t *) (N))->flags |= TREE_NODE_FLG)
-#define SET_LIST_ELEM(N) (((RBTree_t *) (N))->flags &= ~TREE_NODE_FLG)
-
-#define IS_RED(N) (((RBTree_t *) (N)) \
- && ((RBTree_t *) (N))->flags & RED_FLG)
-#define IS_BLACK(N) (!IS_RED(((RBTree_t *) (N))))
-
-#define SET_RED(N) (((RBTree_t *) (N))->flags |= RED_FLG)
-#define SET_BLACK(N) (((RBTree_t *) (N))->flags &= ~RED_FLG)
-
-#undef ASSERT
-#define ASSERT ASSERT_EXPR
-
-#if 1
-#define RBT_ASSERT ASSERT
-#else
-#define RBT_ASSERT(x)
-#endif
-
-
-#ifdef HARD_DEBUG
-static RBTree_t * check_tree(Uint);
-#endif
-
-#ifdef ERTS_INLINE
-# ifndef ERTS_CAN_INLINE
-# define ERTS_CAN_INLINE 1
-# endif
-#else
-# if defined(__GNUC__)
-# define ERTS_CAN_INLINE 1
-# define ERTS_INLINE __inline__
-# elif defined(__WIN32__)
-# define ERTS_CAN_INLINE 1
-# define ERTS_INLINE __inline
-# else
-# define ERTS_CAN_INLINE 0
-# define ERTS_INLINE
-# endif
-#endif
-
-/* Types... */
-#if 0
-typedef struct RBTree_t_ RBTree_t;
-
-struct RBTree_t_ {
- Block_t hdr;
- Uint flags;
- RBTree_t *parent;
- RBTree_t *left;
- RBTree_t *right;
-};
-#endif
-
-#if 0
-typedef struct {
- RBTree_t t;
- RBTree_t *next;
-} RBTreeList_t;
-
-#define LIST_NEXT(N) (((RBTreeList_t *) (N))->next)
-#define LIST_PREV(N) (((RBTreeList_t *) (N))->t.parent)
-#endif
-
-#ifdef DEBUG
-
-/* Destroy all tree fields */
-#define DESTROY_TREE_NODE(N) \
- sys_memset((void *) (((Block_t *) (N)) + 1), \
- 0xff, \
- (sizeof(RBTree_t) - sizeof(Block_t)))
-
-/* Destroy all tree and list fields */
-#define DESTROY_LIST_ELEM(N) \
- sys_memset((void *) (((Block_t *) (N)) + 1), \
- 0xff, \
- (sizeof(RBTreeList_t) - sizeof(Block_t)))
-
-#else
-
-#define DESTROY_TREE_NODE(N)
-#define DESTROY_LIST_ELEM(N)
-
-#endif
-
-
-/*
- * Red-Black Tree operations needed
- */
-
-static ERTS_INLINE void
-left_rotate(RBTree_t **root, RBTree_t *x)
-{
- RBTree_t *y = x->right;
- x->right = y->left;
- if (y->left)
- y->left->parent = x;
- y->parent = x->parent;
- if (!y->parent) {
- RBT_ASSERT(*root == x);
- *root = y;
- }
- else if (x == x->parent->left)
- x->parent->left = y;
- else {
- RBT_ASSERT(x == x->parent->right);
- x->parent->right = y;
- }
- y->left = x;
- x->parent = y;
-}
-
-static ERTS_INLINE void
-right_rotate(RBTree_t **root, RBTree_t *x)
-{
- RBTree_t *y = x->left;
- x->left = y->right;
- if (y->right)
- y->right->parent = x;
- y->parent = x->parent;
- if (!y->parent) {
- RBT_ASSERT(*root == x);
- *root = y;
- }
- else if (x == x->parent->right)
- x->parent->right = y;
- else {
- RBT_ASSERT(x == x->parent->left);
- x->parent->left = y;
- }
- y->right = x;
- x->parent = y;
-}
-
-
-/*
- * Replace node x with node y
- * NOTE: block header of y is not changed
- */
-static ERTS_INLINE void
-replace(RBTree_t **root, RBTree_t *x, RBTree_t *y)
-{
-
- if (!x->parent) {
- RBT_ASSERT(*root == x);
- *root = y;
- }
- else if (x == x->parent->left)
- x->parent->left = y;
- else {
- RBT_ASSERT(x == x->parent->right);
- x->parent->right = y;
- }
- if (x->left) {
- RBT_ASSERT(x->left->parent == x);
- x->left->parent = y;
- }
- if (x->right) {
- RBT_ASSERT(x->right->parent == x);
- x->right->parent = y;
- }
-
- y->flags = x->flags;
- y->parent = x->parent;
- y->right = x->right;
- y->left = x->left;
-
- DESTROY_TREE_NODE(x);
-
-}
-
-static void
-tree_insert_fixup(RBTree_t *blk)
-{
- RBTree_t *x = blk, *y;
-
- /*
- * Rearrange the tree so that it satisfies the Red-Black Tree properties
- */
-
- RBT_ASSERT(x != root && IS_RED(x->parent));
- do {
-
- /*
- * x and its parent are both red. Move the red pair up the tree
- * until we get to the root or until we can separate them.
- */
-
- RBT_ASSERT(IS_RED(x));
- RBT_ASSERT(IS_BLACK(x->parent->parent));
- RBT_ASSERT(x->parent->parent);
-
- if (x->parent == x->parent->parent->left) {
- y = x->parent->parent->right;
- if (IS_RED(y)) {
- SET_BLACK(y);
- x = x->parent;
- SET_BLACK(x);
- x = x->parent;
- SET_RED(x);
- }
- else {
-
- if (x == x->parent->right) {
- x = x->parent;
- left_rotate(&root, x);
- }
-
- RBT_ASSERT(x == x->parent->parent->left->left);
- RBT_ASSERT(IS_RED(x));
- RBT_ASSERT(IS_RED(x->parent));
- RBT_ASSERT(IS_BLACK(x->parent->parent));
- RBT_ASSERT(IS_BLACK(y));
-
- SET_BLACK(x->parent);
- SET_RED(x->parent->parent);
- right_rotate(&root, x->parent->parent);
-
- RBT_ASSERT(x == x->parent->left);
- RBT_ASSERT(IS_RED(x));
- RBT_ASSERT(IS_RED(x->parent->right));
- RBT_ASSERT(IS_BLACK(x->parent));
- break;
- }
- }
- else {
- RBT_ASSERT(x->parent == x->parent->parent->right);
- y = x->parent->parent->left;
- if (IS_RED(y)) {
- SET_BLACK(y);
- x = x->parent;
- SET_BLACK(x);
- x = x->parent;
- SET_RED(x);
- }
- else {
-
- if (x == x->parent->left) {
- x = x->parent;
- right_rotate(&root, x);
- }
-
- RBT_ASSERT(x == x->parent->parent->right->right);
- RBT_ASSERT(IS_RED(x));
- RBT_ASSERT(IS_RED(x->parent));
- RBT_ASSERT(IS_BLACK(x->parent->parent));
- RBT_ASSERT(IS_BLACK(y));
-
- SET_BLACK(x->parent);
- SET_RED(x->parent->parent);
- left_rotate(&root, x->parent->parent);
-
- RBT_ASSERT(x == x->parent->right);
- RBT_ASSERT(IS_RED(x));
- RBT_ASSERT(IS_RED(x->parent->left));
- RBT_ASSERT(IS_BLACK(x->parent));
- break;
- }
- }
- } while (x != root && IS_RED(x->parent));
-
- SET_BLACK(root);
-}
-
-static void
-unlink_free_block(Block_t *del)
-{
- Uint spliced_is_black;
- RBTree_t *x, *y, *z = (RBTree_t *) del;
- RBTree_t null_x; /* null_x is used to get the fixup started when we
- splice out a node without children. */
-
- null_x.parent = NULL;
-
-#ifdef HARD_DEBUG
- check_tree(0);
-#endif
-
- /* Remove node from tree... */
-
- /* Find node to splice out */
- if (!z->left || !z->right)
- y = z;
- else
- /* Set y to z:s successor */
- for(y = z->right; y->left; y = y->left);
- /* splice out y */
- x = y->left ? y->left : y->right;
- spliced_is_black = IS_BLACK(y);
- if (x) {
- x->parent = y->parent;
- }
- else if (!x && spliced_is_black) {
- x = &null_x;
- x->flags = 0;
- SET_BLACK(x);
- x->right = x->left = NULL;
- x->parent = y->parent;
- y->left = x;
- }
-
- if (!y->parent) {
- RBT_ASSERT(root == y);
- root = x;
- }
- else if (y == y->parent->left)
- y->parent->left = x;
- else {
- RBT_ASSERT(y == y->parent->right);
- y->parent->right = x;
- }
- if (y != z) {
- /* We spliced out the successor of z; replace z by the successor */
- replace(&root, z, y);
- }
-
- if (spliced_is_black) {
- /* We removed a black node which makes the resulting tree
- violate the Red-Black Tree properties. Fixup tree... */
-
- while (IS_BLACK(x) && x->parent) {
-
- /*
- * x has an "extra black" which we move up the tree
- * until we reach the root or until we can get rid of it.
- *
- * y is the sibbling of x
- */
-
- if (x == x->parent->left) {
- y = x->parent->right;
- RBT_ASSERT(y);
- if (IS_RED(y)) {
- RBT_ASSERT(y->right);
- RBT_ASSERT(y->left);
- SET_BLACK(y);
- RBT_ASSERT(IS_BLACK(x->parent));
- SET_RED(x->parent);
- left_rotate(&root, x->parent);
- y = x->parent->right;
- }
- RBT_ASSERT(y);
- RBT_ASSERT(IS_BLACK(y));
- if (IS_BLACK(y->left) && IS_BLACK(y->right)) {
- SET_RED(y);
- x = x->parent;
- }
- else {
- if (IS_BLACK(y->right)) {
- SET_BLACK(y->left);
- SET_RED(y);
- right_rotate(&root, y);
- y = x->parent->right;
- }
- RBT_ASSERT(y);
- if (IS_RED(x->parent)) {
-
- SET_BLACK(x->parent);
- SET_RED(y);
- }
- RBT_ASSERT(y->right);
- SET_BLACK(y->right);
- left_rotate(&root, x->parent);
- x = root;
- break;
- }
- }
- else {
- RBT_ASSERT(x == x->parent->right);
- y = x->parent->left;
- RBT_ASSERT(y);
- if (IS_RED(y)) {
- RBT_ASSERT(y->right);
- RBT_ASSERT(y->left);
- SET_BLACK(y);
- RBT_ASSERT(IS_BLACK(x->parent));
- SET_RED(x->parent);
- right_rotate(&root, x->parent);
- y = x->parent->left;
- }
- RBT_ASSERT(y);
- RBT_ASSERT(IS_BLACK(y));
- if (IS_BLACK(y->right) && IS_BLACK(y->left)) {
- SET_RED(y);
- x = x->parent;
- }
- else {
- if (IS_BLACK(y->left)) {
- SET_BLACK(y->right);
- SET_RED(y);
- left_rotate(&root, y);
- y = x->parent->left;
- }
- RBT_ASSERT(y);
- if (IS_RED(x->parent)) {
- SET_BLACK(x->parent);
- SET_RED(y);
- }
- RBT_ASSERT(y->left);
- SET_BLACK(y->left);
- right_rotate(&root, x->parent);
- x = root;
- break;
- }
- }
- }
- SET_BLACK(x);
-
- if (null_x.parent) {
- if (null_x.parent->left == &null_x)
- null_x.parent->left = NULL;
- else {
- RBT_ASSERT(null_x.parent->right == &null_x);
- null_x.parent->right = NULL;
- }
- RBT_ASSERT(!null_x.left);
- RBT_ASSERT(!null_x.right);
- }
- else if (root == &null_x) {
- root = NULL;
- RBT_ASSERT(!null_x.left);
- RBT_ASSERT(!null_x.right);
- }
- }
-
-
- DESTROY_TREE_NODE(del);
-
-#ifdef HARD_DEBUG
- check_tree(0);
-#endif
-
-}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
- * "Address order best fit" specific callbacks. *
-\* */
-
-static void
-link_free_block(Block_t *block)
-{
- RBTree_t *blk = (RBTree_t *) block;
- Uint blk_sz = BLK_SZ(blk);
-
- blk->flags = 0;
- blk->left = NULL;
- blk->right = NULL;
-
- if (!root) {
- blk->parent = NULL;
- SET_BLACK(blk);
- root = blk;
- } else {
- RBTree_t *x = root;
- while (1) {
- Uint size;
-
- size = BLK_SZ(x);
-
- if (blk_sz < size || (blk_sz == size && blk < x)) {
- if (!x->left) {
- blk->parent = x;
- x->left = blk;
- break;
- }
- x = x->left;
- }
- else {
- if (!x->right) {
- blk->parent = x;
- x->right = blk;
- break;
- }
- x = x->right;
- }
-
- }
-
- /* Insert block into size tree */
- RBT_ASSERT(blk->parent);
-
- SET_RED(blk);
- if (IS_RED(blk->parent)) {
- tree_insert_fixup(blk);
- }
- }
-
-#ifdef HARD_DEBUG
- check_tree(0);
-#endif
-}
-
-
-static Block_t *
-get_free_block(Uint size)
-{
- RBTree_t *x = root;
- RBTree_t *blk = NULL;
- Uint blk_sz;
-
- while (x) {
- blk_sz = BLK_SZ(x);
- if (blk_sz < size) {
- x = x->right;
- }
- else {
- blk = x;
- x = x->left;
- }
- }
-
- if (!blk)
- return NULL;
-
-#ifdef HARD_DEBUG
- ASSERT(blk == check_tree(size));
-#endif
-
- unlink_free_block((Block_t *) blk);
-
- return (Block_t *) blk;
-}
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
- * Debug functions *
-\* */
-
-
-#ifdef HARD_DEBUG
-
-#define IS_LEFT_VISITED(FB) ((FB)->flags & LEFT_VISITED_FLG)
-#define IS_RIGHT_VISITED(FB) ((FB)->flags & RIGHT_VISITED_FLG)
-
-#define SET_LEFT_VISITED(FB) ((FB)->flags |= LEFT_VISITED_FLG)
-#define SET_RIGHT_VISITED(FB) ((FB)->flags |= RIGHT_VISITED_FLG)
-
-#define UNSET_LEFT_VISITED(FB) ((FB)->flags &= ~LEFT_VISITED_FLG)
-#define UNSET_RIGHT_VISITED(FB) ((FB)->flags &= ~RIGHT_VISITED_FLG)
-
-
-#if 0
-# define PRINT_TREE
-#else
-# undef PRINT_TREE
-#endif
-
-#ifdef PRINT_TREE
-static void print_tree(void);
-#endif
-
-/*
- * Checks that the order between parent and children are correct,
- * and that the Red-Black Tree properies are satisfied. if size > 0,
- * check_tree() returns a node that satisfies "best fit" resp.
- * "address order best fit".
- *
- * The Red-Black Tree properies are:
- * 1. Every node is either red or black.
- * 2. Every leaf (NIL) is black.
- * 3. If a node is red, then both its children are black.
- * 4. Every simple path from a node to a descendant leaf
- * contains the same number of black nodes.
- */
-
-static RBTree_t *
-check_tree(Uint size)
-{
- RBTree_t *res = NULL;
- Sint blacks;
- Sint curr_blacks;
- RBTree_t *x;
-
-#ifdef PRINT_TREE
- print_tree();
-#endif
-
- if (!root)
- return res;
-
- x = root;
- ASSERT(IS_BLACK(x));
- ASSERT(!x->parent);
- curr_blacks = 1;
- blacks = -1;
-
- while (x) {
- if (!IS_LEFT_VISITED(x)) {
- SET_LEFT_VISITED(x);
- if (x->left) {
- x = x->left;
- if (IS_BLACK(x))
- curr_blacks++;
- continue;
- }
- else {
- if (blacks < 0)
- blacks = curr_blacks;
- ASSERT(blacks == curr_blacks);
- }
- }
-
- if (!IS_RIGHT_VISITED(x)) {
- SET_RIGHT_VISITED(x);
- if (x->right) {
- x = x->right;
- if (IS_BLACK(x))
- curr_blacks++;
- continue;
- }
- else {
- if (blacks < 0)
- blacks = curr_blacks;
- ASSERT(blacks == curr_blacks);
- }
- }
-
-
- if (IS_RED(x)) {
- ASSERT(IS_BLACK(x->right));
- ASSERT(IS_BLACK(x->left));
- }
-
- ASSERT(x->parent || x == root);
-
- if (x->left) {
- ASSERT(x->left->parent == x);
- ASSERT(BLK_SZ(x->left) < BLK_SZ(x)
- || (BLK_SZ(x->left) == BLK_SZ(x) && x->left < x));
- }
-
- if (x->right) {
- ASSERT(x->right->parent == x);
- ASSERT(BLK_SZ(x->right) > BLK_SZ(x)
- || (BLK_SZ(x->right) == BLK_SZ(x) && x->right > x));
- }
-
- if (size && BLK_SZ(x) >= size) {
- if (!res
- || BLK_SZ(x) < BLK_SZ(res)
- || (BLK_SZ(x) == BLK_SZ(res) && x < res))
- res = x;
- }
-
- UNSET_LEFT_VISITED(x);
- UNSET_RIGHT_VISITED(x);
- if (IS_BLACK(x))
- curr_blacks--;
- x = x->parent;
-
- }
-
- ASSERT(curr_blacks == 0);
-
- UNSET_LEFT_VISITED(root);
- UNSET_RIGHT_VISITED(root);
-
- return res;
-
-}
-
-
-#ifdef PRINT_TREE
-#define INDENT_STEP 2
-
-#include <stdio.h>
-
-static void
-print_tree_aux(RBTree_t *x, int indent)
-{
- int i;
-
- if (!x) {
- for (i = 0; i < indent; i++) {
- putc(' ', stderr);
- }
- fprintf(stderr, "BLACK: nil\r\n");
- }
- else {
- print_tree_aux(x->right, indent + INDENT_STEP);
- for (i = 0; i < indent; i++) {
- putc(' ', stderr);
- }
- fprintf(stderr, "%s: sz=%lu addr=0x%lx\r\n",
- IS_BLACK(x) ? "BLACK" : "RED",
- BLK_SZ(x),
- (Uint) x);
- print_tree_aux(x->left, indent + INDENT_STEP);
- }
-}
-
-
-static void
-print_tree(void)
-{
- fprintf(stderr, " --- Size-Adress tree begin ---\r\n");
- print_tree_aux(root, 0);
- fprintf(stderr, " --- Size-Adress tree end ---\r\n");
-}
-
-#endif
-
-#endif
-
-#endif /* ENABLE_ELIB_MALLOC */
diff --git a/erts/emulator/beam/elib_stat.h b/erts/emulator/beam/elib_stat.h
deleted file mode 100644
index d8c7f31737..0000000000
--- a/erts/emulator/beam/elib_stat.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1996-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%
- */
-
-/*
-** Interface to elib statistics
-**
-*/
-#ifndef __ELIB_STAT_H__
-#define __ELIB_STAT_H__
-
-struct elib_stat {
- int mem_total; /* Number of heap words */
- int mem_blocks; /* Number of block */
- int mem_alloc; /* Number of words in use */
- int mem_free; /* Number of words free */
- int min_used; /* Size of the smallest block used */
- int max_free; /* Size of the largest free block */
- int free_blocks; /* Number of fragments in free list */
- int mem_max_alloc;/* Max number of words in use */
-};
-
-EXTERN_FUNCTION(void, elib_statistics, (void*));
-EXTERN_FUNCTION(int, elib_check_heap, (_VOID_));
-EXTERN_FUNCTION(void, elib_heap_dump, (char*));
-EXTERN_FUNCTION(void, elib_stat, (struct elib_stat*));
-EXTERN_FUNCTION(int, elib_heap_map, (unsigned char*, int));
-EXTERN_FUNCTION(int, elib_histo, (unsigned long*, unsigned long*, int, int));
-
-#endif
diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c
index 87503af7d5..07b4167b27 100644
--- a/erts/emulator/beam/erl_alloc.c
+++ b/erts/emulator/beam/erl_alloc.c
@@ -38,9 +38,6 @@
#include "erl_bits.h"
#include "erl_instrument.h"
#include "erl_mseg.h"
-#ifdef ELIB_ALLOC_IS_CLIB
-#include "erl_version.h"
-#endif
#include "erl_monitors.h"
#include "erl_bif_timer.h"
#if defined(ERTS_ALC_T_DRV_SEL_D_STATE) || defined(ERTS_ALC_T_DRV_EV_D_STATE)
@@ -73,7 +70,6 @@ static Uint install_debug_functions(void);
#endif
#endif
#endif
-extern void elib_ensure_initialized(void);
ErtsAllocatorFunctions_t erts_allctrs[ERTS_ALC_A_MAX+1];
ErtsAllocatorInfo_t erts_allctrs_info[ERTS_ALC_A_MAX+1];
@@ -2321,13 +2317,8 @@ erts_allocator_info_term(void *proc, Eterm which_alloc, int only_sz)
l = 0;
as[l] = am_atom_put("e", 1);
ts[l++] = am_true;
-#ifdef ELIB_ALLOC_IS_CLIB
- as[l] = am_atom_put("m", 1);
- ts[l++] = am_atom_put("elib", 4);
-#else
as[l] = am_atom_put("m", 1);
ts[l++] = am_atom_put("libc", 4);
-#endif
if(sas.trim_threshold >= 0) {
as[l] = am_atom_put("tt", 2);
ts[l++] = erts_bld_uint(hpp, szp,
@@ -2481,11 +2472,7 @@ erts_allocator_info(int to, void *arg)
case ERTS_ALC_A_SYSTEM: {
SysAllocStat sas;
erts_print(to, arg, "option e: true\n");
-#ifdef ELIB_ALLOC_IS_CLIB
- erts_print(to, arg, "option m: elib\n");
-#else
erts_print(to, arg, "option m: libc\n");
-#endif
sys_alloc_stat(&sas);
if(sas.trim_threshold >= 0)
erts_print(to, arg, "option tt: %d\n", sas.trim_threshold);
@@ -2589,13 +2576,8 @@ erts_allocator_options(void *proc)
switch (a) {
case ERTS_ALC_A_SYSTEM:
-#ifdef ELIB_ALLOC_IS_CLIB
- as[l] = am_atom_put("m", 1);
- ts[l++] = am_atom_put("elib", 4);
-#else
as[l] = am_atom_put("m", 1);
ts[l++] = am_atom_put("libc", 4);
-#endif
if(sas.trim_threshold >= 0) {
as[l] = am_atom_put("tt", 2);
ts[l++] = erts_bld_uint(hpp, szp,
@@ -2666,23 +2648,7 @@ erts_allocator_options(void *proc)
features = length ? erts_bld_list(hpp, szp, length, terms) : NIL;
-#if defined(ELIB_ALLOC_IS_CLIB)
- {
- Eterm version;
- int i;
- int ver[5];
- i = sscanf(ERLANG_VERSION,
- "%d.%d.%d.%d.%d",
- &ver[0], &ver[1], &ver[2], &ver[3], &ver[4]);
-
- version = NIL;
- for(i--; i >= 0; i--)
- version = erts_bld_cons(hpp, szp, make_small(ver[i]), version);
-
- res = erts_bld_tuple(hpp, szp, 4,
- am_elib_malloc, version, features, settings);
- }
-#elif defined(__GLIBC__)
+#if defined(__GLIBC__)
{
Eterm AM_glibc = am_atom_put("glibc", 5);
Eterm version;
diff --git a/erts/emulator/beam/erl_async.c b/erts/emulator/beam/erl_async.c
index be691317ee..12c7631448 100644
--- a/erts/emulator/beam/erl_async.c
+++ b/erts/emulator/beam/erl_async.c
@@ -70,7 +70,6 @@ static ErlAsync* async_ready_list = NULL;
/* Detach from driver */
static void async_detach(DE_Handle* dh)
{
- /* XXX:PaN what should happen here? we want to unload the driver or??? */
return;
}
@@ -176,7 +175,6 @@ int exit_async()
static void async_add(ErlAsync* a, AsyncQueue* q)
{
- /* XXX:PaN Is this still necessary when ports lock drivers? */
if (is_internal_port(a->port)) {
ERTS_LC_ASSERT(erts_drvportid2port(a->port));
/* make sure the driver will stay around */
diff --git a/erts/emulator/beam/erl_bif_binary.c b/erts/emulator/beam/erl_bif_binary.c
index 1d8fd11b7b..b6a445c55c 100644
--- a/erts/emulator/beam/erl_bif_binary.c
+++ b/erts/emulator/beam/erl_bif_binary.c
@@ -555,8 +555,12 @@ static void ac_init_find_all(ACFindAllState *state, ACTrie *act, Sint startpos,
static void ac_restore_find_all(ACFindAllState *state, char *buff)
{
memcpy(state,buff,sizeof(ACFindAllState));
- state->out = erts_alloc(ERTS_ALC_T_TMP, sizeof(FindallData) * (state->allocated));
- memcpy(state->out,buff+sizeof(ACFindAllState),sizeof(FindallData)*state->m);
+ if (state->allocated > 0) {
+ state->out = erts_alloc(ERTS_ALC_T_TMP, sizeof(FindallData) * (state->allocated));
+ memcpy(state->out,buff+sizeof(ACFindAllState),sizeof(FindallData)*state->m);
+ } else {
+ state->out = NULL;
+ }
}
static void ac_serialize_find_all(ACFindAllState *state, char *buff)
@@ -828,10 +832,14 @@ static void bm_init_find_all(BMFindAllState *state, Sint startpos, Uint len)
static void bm_restore_find_all(BMFindAllState *state, char *buff)
{
memcpy(state,buff,sizeof(BMFindAllState));
- state->out = erts_alloc(ERTS_ALC_T_TMP, sizeof(FindallData) *
- (state->allocated));
- memcpy(state->out,buff+sizeof(BMFindAllState),
- sizeof(FindallData)*state->m);
+ if (state->allocated > 0) {
+ state->out = erts_alloc(ERTS_ALC_T_TMP, sizeof(FindallData) *
+ (state->allocated));
+ memcpy(state->out,buff+sizeof(BMFindAllState),
+ sizeof(FindallData)*state->m);
+ } else {
+ state->out = NULL;
+ }
}
static void bm_serialize_find_all(BMFindAllState *state, char *buff)
@@ -1128,7 +1136,7 @@ static int do_binary_match(Process *p, Eterm subject, Uint hsstart, Uint hsend,
ret = am_nomatch;
} else if (acr == AC_RESTART) {
int x = (sizeof(state) / sizeof(Eterm)) +
- !!(sizeof(BMFindFirstState) % sizeof(Eterm));
+ !!(sizeof(ACFindFirstState) % sizeof(Eterm));
#ifdef HARDDEBUG
erts_printf("Trap ac!\n");
#endif
@@ -2517,7 +2525,7 @@ BIF_RETTYPE binary_copy_trap(BIF_ALIST_2)
pb->bytes = t;
pb->flags = 0;
- MSO(BIF_P).overhead += target_size / sizeof(Eterm);
+ OH_OVERHEAD(&(MSO(BIF_P)), target_size / sizeof(Eterm));
BUMP_REDS(BIF_P,(pos - opos) / BINARY_COPY_LOOP_FACTOR);
BIF_RET(make_binary(pb));
@@ -2551,7 +2559,8 @@ BIF_RETTYPE binary_referenced_byte_size_1(BIF_ALIST_1)
}
pb = (ProcBin *) binary_val(bin);
if (pb->thing_word == HEADER_PROC_BIN) {
- res = erts_make_integer((Uint) pb->val->orig_size, BIF_P); /* XXX:PaN Halfword? orig_size is a long */
+ /* XXX:PaN - Halfword - orig_size is a long, we should handle that */
+ res = erts_make_integer((Uint) pb->val->orig_size, BIF_P);
} else { /* heap binary */
res = erts_make_integer((Uint) ((ErlHeapBin *) pb)->size, BIF_P);
}
diff --git a/erts/emulator/beam/erl_bif_ddll.c b/erts/emulator/beam/erl_bif_ddll.c
index 9d5f0d9c02..2c2e283f65 100644
--- a/erts/emulator/beam/erl_bif_ddll.c
+++ b/erts/emulator/beam/erl_bif_ddll.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2006-2009. All Rights Reserved.
+ * Copyright Ericsson AB 2006-2010. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -1646,7 +1646,8 @@ static int do_unload_driver_entry(DE_Handle *dh, Eterm *save_name)
if (save_name != NULL) {
*save_name = mkatom(q->name);
}
- /* XXX:PaN Future locking problems? Don't dare to let go of the diver_list lock here!*/
+ /* Future locking problems? Don't dare to let go of the
+ diver_list lock here!*/
if (q->finish) {
int fpe_was_unmasked = erts_block_fpe();
(*(q->finish))();
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c
index 5128776c47..2f3e23f879 100644
--- a/erts/emulator/beam/erl_bif_info.c
+++ b/erts/emulator/beam/erl_bif_info.c
@@ -38,9 +38,6 @@
#include "erl_instrument.h"
#include "dist.h"
#include "erl_gc.h"
-#ifdef ELIB_ALLOC_IS_CLIB
-#include "elib_stat.h"
-#endif
#ifdef HIPE
#include "hipe_arch.h"
#endif
@@ -1690,6 +1687,8 @@ info_1_tuple(Process* BIF_P, /* Pointer to current process. */
return erts_get_cpu_topology_term(BIF_P, *tp);
} else if (ERTS_IS_ATOM_STR("cpu_topology", sel) && arity == 2) {
Eterm res = erts_get_cpu_topology_term(BIF_P, *tp);
+ if (res == THE_NON_VALUE)
+ goto badarg;
ERTS_BIF_PREP_TRAP1(ret, erts_format_cpu_topology_trap, BIF_P, res);
return ret;
#if defined(PURIFY) || defined(VALGRIND)
@@ -1958,6 +1957,35 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
: am_enabled);
}
#endif
+ } else if (BIF_ARG_1 == am_build_type) {
+#if defined(DEBUG)
+ ERTS_DECL_AM(debug);
+ BIF_RET(AM_debug);
+#elif defined(PURIFY)
+ ERTS_DECL_AM(purify);
+ BIF_RET(AM_purify);
+#elif defined(QUANTIFY)
+ ERTS_DECL_AM(quantify);
+ BIF_RET(AM_quantify);
+#elif defined(PURECOV)
+ ERTS_DECL_AM(purecov);
+ BIF_RET(AM_purecov);
+#elif defined(ERTS_GCOV)
+ ERTS_DECL_AM(gcov);
+ BIF_RET(AM_gcov);
+#elif defined(VALGRIND)
+ ERTS_DECL_AM(valgrind);
+ BIF_RET(AM_valgrind);
+#elif defined(GPROF)
+ ERTS_DECL_AM(gprof);
+ BIF_RET(AM_gprof);
+#elif defined(ERTS_ENABLE_LOCK_COUNT)
+ ERTS_DECL_AM(lcnt);
+ BIF_RET(AM_lcnt);
+#else
+ BIF_RET(am_opt);
+#endif
+ BIF_RET(res);
} else if (BIF_ARG_1 == am_allocated_areas) {
res = erts_allocated_areas(NULL, NULL, BIF_P);
BIF_RET(res);
@@ -2126,86 +2154,8 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
BIF_RET(erts_alloc_util_allocators((void *) BIF_P));
}
else if (BIF_ARG_1 == am_elib_malloc) {
-#ifdef ELIB_ALLOC_IS_CLIB
- struct elib_stat stat;
- DECL_AM(heap_size);
- DECL_AM(max_alloced_size);
- DECL_AM(alloced_size);
- DECL_AM(free_size);
- DECL_AM(no_alloced_blocks);
- DECL_AM(no_free_blocks);
- DECL_AM(smallest_alloced_block);
- DECL_AM(largest_free_block);
- Eterm atoms[8];
- Eterm ints[8];
- Uint **hpp;
- Uint sz;
- Uint *szp;
- int length;
-#ifdef DEBUG
- Uint *endp;
-#endif
-
- elib_stat(&stat);
-
- /* First find out the heap size needed ... */
- hpp = NULL;
- szp = &sz;
- sz = 0;
-
- build_elib_malloc_term:
- length = 0;
- atoms[length] = AM_heap_size;
- ints[length++] = erts_bld_uint(hpp, szp,
- (Uint) stat.mem_total*sizeof(Uint));
- atoms[length] = AM_max_alloced_size;
- ints[length++] = erts_bld_uint(hpp, szp,
- (Uint) stat.mem_max_alloc*sizeof(Uint));
- atoms[length] = AM_alloced_size;
- ints[length++] = erts_bld_uint(hpp, szp,
- (Uint) stat.mem_alloc*sizeof(Uint));
- atoms[length] = AM_free_size;
- ints[length++] = erts_bld_uint(hpp, szp,
- (Uint) stat.mem_free*sizeof(Uint));
- atoms[length] = AM_no_alloced_blocks;
- ints[length++] = erts_bld_uint(hpp, szp, (Uint) stat.mem_blocks);
- atoms[length] = AM_no_free_blocks;
- ints[length++] = erts_bld_uint(hpp, szp, (Uint) stat.free_blocks);
- atoms[length] = AM_smallest_alloced_block;
- ints[length++] = erts_bld_uint(hpp, szp,
- (Uint) stat.min_used*sizeof(Uint));
- atoms[length] = AM_largest_free_block;
- ints[length++] = erts_bld_uint(hpp, szp,
- (Uint) stat.max_free*sizeof(Uint));
-
-
-
- ASSERT(length <= sizeof(atoms)/sizeof(Eterm));
- ASSERT(length <= sizeof(ints)/sizeof(Eterm));
-
- res = erts_bld_2tup_list(hpp, szp, length, atoms, ints);
-
- if (szp) {
- /* ... and then build the term */
- hp = HAlloc(BIF_P, sz);
-#ifdef DEBUG
- endp = hp + sz;
-#endif
-
- szp = NULL;
- hpp = &hp;
- goto build_elib_malloc_term;
- }
-
-#ifdef DEBUG
- ASSERT(endp == hp);
-#endif
-
-#else /* #ifdef ELIB_ALLOC_IS_CLIB */
- res = am_false;
-#endif /* #ifdef ELIB_ALLOC_IS_CLIB */
-
- BIF_RET(res);
+ /* To be removed in R15 */
+ BIF_RET(am_false);
}
else if (BIF_ARG_1 == am_os_version) {
int major, minor, build;
@@ -2316,6 +2266,15 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
} else if (ERTS_IS_ATOM_STR("cpu_topology", BIF_ARG_1)) {
res = erts_get_cpu_topology_term(BIF_P, am_used);
BIF_TRAP1(erts_format_cpu_topology_trap, BIF_P, res);
+ } else if (ERTS_IS_ATOM_STR("update_cpu_info", BIF_ARG_1)) {
+ if (erts_update_cpu_info()) {
+ ERTS_DECL_AM(changed);
+ BIF_RET(AM_changed);
+ }
+ else {
+ ERTS_DECL_AM(unchanged);
+ BIF_RET(AM_unchanged);
+ }
#if defined(__GNUC__) && defined(HAVE_SOLARIS_SPARC_PERFMON)
} else if (ERTS_IS_ATOM_STR("ultrasparc_read_tick1", BIF_ARG_1)) {
register unsigned high asm("%l0");
@@ -2387,7 +2346,10 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
}
/* Arguments that are unusual follow ... */
else if (ERTS_IS_ATOM_STR("logical_processors", BIF_ARG_1)) {
- int no = erts_get_cpu_configured(erts_cpuinfo);
+ int no;
+ erts_smp_rwmtx_rlock(&erts_cpu_bind_rwmtx);
+ no = erts_get_cpu_configured(erts_cpuinfo);
+ erts_smp_rwmtx_runlock(&erts_cpu_bind_rwmtx);
if (no > 0)
BIF_RET(make_small((Uint) no));
else {
@@ -2396,7 +2358,10 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
}
}
else if (ERTS_IS_ATOM_STR("logical_processors_online", BIF_ARG_1)) {
- int no = erts_get_cpu_online(erts_cpuinfo);
+ int no;
+ erts_smp_rwmtx_rlock(&erts_cpu_bind_rwmtx);
+ no = erts_get_cpu_online(erts_cpuinfo);
+ erts_smp_rwmtx_runlock(&erts_cpu_bind_rwmtx);
if (no > 0)
BIF_RET(make_small((Uint) no));
else {
@@ -2405,7 +2370,10 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
}
}
else if (ERTS_IS_ATOM_STR("logical_processors_available", BIF_ARG_1)) {
- int no = erts_get_cpu_available(erts_cpuinfo);
+ int no;
+ erts_smp_rwmtx_rlock(&erts_cpu_bind_rwmtx);
+ no = erts_get_cpu_available(erts_cpuinfo);
+ erts_smp_rwmtx_runlock(&erts_cpu_bind_rwmtx);
if (no > 0)
BIF_RET(make_small((Uint) no));
else {
@@ -2567,6 +2535,13 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
BIF_RET(erts_nif_taints(BIF_P));
} else if (ERTS_IS_ATOM_STR("reader_groups_map", BIF_ARG_1)) {
BIF_RET(erts_get_reader_groups_map(BIF_P));
+ } else if (ERTS_IS_ATOM_STR("dist_buf_busy_limit", BIF_ARG_1)) {
+ Uint hsz = 0;
+
+ (void) erts_bld_uint(NULL, &hsz, erts_dist_buf_busy_limit);
+ hp = hsz ? HAlloc(BIF_P, hsz) : NULL;
+ res = erts_bld_uint(&hp, NULL, erts_dist_buf_busy_limit);
+ BIF_RET(res);
}
BIF_ERROR(BIF_P, BADARG);
diff --git a/erts/emulator/beam/erl_bits.c b/erts/emulator/beam/erl_bits.c
index 96faa673f6..88d2c06246 100644
--- a/erts/emulator/beam/erl_bits.c
+++ b/erts/emulator/beam/erl_bits.c
@@ -1340,7 +1340,7 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term,
pb->val = bptr;
pb->bytes = (byte*) bptr->orig_bytes;
pb->flags = PB_IS_WRITABLE | PB_ACTIVE_WRITER;
- MSO(c_p).overhead += pb->size / sizeof(Eterm);
+ OH_OVERHEAD(&(MSO(c_p)), pb->size / sizeof(Eterm));
/*
* Now allocate the sub binary and set its size to include the
@@ -1511,7 +1511,7 @@ erts_bs_init_writable(Process* p, Eterm sz)
pb->val = bptr;
pb->bytes = (byte*) bptr->orig_bytes;
pb->flags = PB_IS_WRITABLE | PB_ACTIVE_WRITER;
- MSO(p).overhead += pb->size / sizeof(Eterm);
+ OH_OVERHEAD(&(MSO(p)), pb->size / sizeof(Eterm));
/*
* Now allocate the sub binary.
diff --git a/erts/emulator/beam/erl_db.c b/erts/emulator/beam/erl_db.c
index b0369a402b..1c2c0fe4cb 100644
--- a/erts/emulator/beam/erl_db.c
+++ b/erts/emulator/beam/erl_db.c
@@ -265,7 +265,7 @@ static ERTS_INLINE void db_init_lock(DbTable* tb, int use_frequent_read_lock,
char *rwname, char* fixname)
{
#ifdef ERTS_SMP
- erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_THR_OPTS_DEFAULT_INITER;
+ erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER;
if (use_frequent_read_lock)
rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ;
#endif
@@ -2746,7 +2746,7 @@ void init_db(void)
size_t size;
#ifdef ERTS_SMP
- erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_THR_OPTS_DEFAULT_INITER;
+ erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER;
rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ;
rwmtx_opt.lived = ERTS_SMP_RWMTX_LONG_LIVED;
@@ -2754,13 +2754,13 @@ void init_db(void)
(sizeof(erts_meta_main_tab_lock_t)
* (ERTS_META_MAIN_TAB_LOCK_TAB_SIZE+1)));
- if ((((Uint) meta_main_tab_locks) & ERTS_CACHE_LINE_MASK) != 0)
+ if ((((UWord) meta_main_tab_locks) & ERTS_CACHE_LINE_MASK) != 0)
meta_main_tab_locks = ((erts_meta_main_tab_lock_t *)
- ((((Uint) meta_main_tab_locks)
+ ((((UWord) meta_main_tab_locks)
& ~ERTS_CACHE_LINE_MASK)
+ ERTS_CACHE_LINE_SIZE));
- ASSERT((((Uint) meta_main_tab_locks) & ERTS_CACHE_LINE_MASK) == 0);
+ ASSERT((((UWord) meta_main_tab_locks) & ERTS_CACHE_LINE_MASK) == 0);
for (i = 0; i < ERTS_META_MAIN_TAB_LOCK_TAB_SIZE; i++) {
erts_smp_rwmtx_init_opt_x(&meta_main_tab_locks[i].rwmtx, &rwmtx_opt,
diff --git a/erts/emulator/beam/erl_db_hash.c b/erts/emulator/beam/erl_db_hash.c
index 08117bb6e5..fa707f4eed 100644
--- a/erts/emulator/beam/erl_db_hash.c
+++ b/erts/emulator/beam/erl_db_hash.c
@@ -623,7 +623,7 @@ int db_create_hash(Process *p, DbTable *tbl)
erts_smp_atomic_init(&tb->is_resizing, 0);
#ifdef ERTS_SMP
if (tb->common.type & DB_FINE_LOCKED) {
- erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_THR_OPTS_DEFAULT_INITER;
+ erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER;
int i;
if (tb->common.type & DB_FREQ_READ)
rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ;
@@ -2745,6 +2745,7 @@ static void db_finalize_dbterm_hash(DbUpdateHandle* handle)
ASSERT(&oldp->dbterm == handle->dbterm);
if (handle->mustResize) {
+ ErlOffHeap tmp_offheap;
Eterm* top;
Eterm copy;
DbTerm* newDbTerm;
@@ -2755,14 +2756,15 @@ static void db_finalize_dbterm_hash(DbUpdateHandle* handle)
newDbTerm = &newp->dbterm;
newDbTerm->size = handle->new_size;
- newDbTerm->off_heap.first = NULL;
- newDbTerm->off_heap.overhead = 0;
+ tmp_offheap.first = NULL;
+ tmp_offheap.overhead = 0;
/* make a flat copy */
top = DBTERM_BUF(newDbTerm);
copy = copy_struct(make_tuple(handle->dbterm->tpl),
handle->new_size,
- &top, &newDbTerm->off_heap);
+ &top, &tmp_offheap);
+ newDbTerm->first_oh = tmp_offheap.first;
DBTERM_SET_TPL(newDbTerm,tuple_val(copy));
WUNLOCK_HASH(lck);
@@ -2805,7 +2807,11 @@ void db_foreach_offheap_hash(DbTable *tbl,
for (i = 0; i < nactive; i++) {
list = BUCKET(tb,i);
while(list != 0) {
- (*func)(&(list->dbterm.off_heap), arg);
+ ErlOffHeap tmp_offheap;
+ tmp_offheap.first = list->dbterm.first_oh;
+ tmp_offheap.overhead = 0;
+ (*func)(&tmp_offheap, arg);
+ list->dbterm.first_oh = tmp_offheap.first;
list = list->next;
}
}
diff --git a/erts/emulator/beam/erl_db_tree.c b/erts/emulator/beam/erl_db_tree.c
index da2696163a..5644e85f97 100644
--- a/erts/emulator/beam/erl_db_tree.c
+++ b/erts/emulator/beam/erl_db_tree.c
@@ -1818,10 +1818,14 @@ do_db_tree_foreach_offheap(TreeDbTerm *tdbt,
void (*func)(ErlOffHeap *, void *),
void * arg)
{
+ ErlOffHeap tmp_offheap;
if(!tdbt)
return;
do_db_tree_foreach_offheap(tdbt->left, func, arg);
- (*func)(&(tdbt->dbterm.off_heap), arg);
+ tmp_offheap.first = tdbt->dbterm.first_oh;
+ tmp_offheap.overhead = 0;
+ (*func)(&tmp_offheap, arg);
+ tdbt->dbterm.first_oh = tmp_offheap.first;
do_db_tree_foreach_offheap(tdbt->right, func, arg);
}
@@ -2575,6 +2579,7 @@ static int db_lookup_dbterm_tree(DbTable *tbl, Eterm key, DbUpdateHandle* handle
static void db_finalize_dbterm_tree(DbUpdateHandle* handle)
{
if (handle->mustResize) {
+ ErlOffHeap tmp_offheap;
Eterm* top;
Eterm copy;
DbTerm* newDbTerm;
@@ -2589,14 +2594,15 @@ static void db_finalize_dbterm_tree(DbUpdateHandle* handle)
newDbTerm = &newp->dbterm;
newDbTerm->size = handle->new_size;
- newDbTerm->off_heap.first = NULL;
- newDbTerm->off_heap.overhead = 0;
+ tmp_offheap.first = NULL;
+ tmp_offheap.overhead = 0;
/* make a flat copy */
top = DBTERM_BUF(newDbTerm);
copy = copy_struct(make_tuple(handle->dbterm->tpl),
handle->new_size,
- &top, &newDbTerm->off_heap);
+ &top, &tmp_offheap);
+ newDbTerm->first_oh = tmp_offheap.first;
DBTERM_SET_TPL(newDbTerm,tuple_val(copy));
db_free_term_data(handle->dbterm);
diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c
index 48e0080525..2f34561234 100644
--- a/erts/emulator/beam/erl_db_util.c
+++ b/erts/emulator/beam/erl_db_util.c
@@ -1733,8 +1733,7 @@ restart:
FAIL();
ep = termp;
break;
- case matchArrayBind: /* When the array size is unknown. */ /* XXX:PaN - where does
- this array come from? */
+ case matchArrayBind: /* When the array size is unknown. */
n = *pc++;
hp[n] = dpm_array_to_list(psp, termp, arity);
break;
@@ -2452,9 +2451,13 @@ void* db_get_term(DbTableCommon *tb, DbTerm* old, Uint offset, Eterm obj)
DbTerm* p;
Eterm copy;
Eterm *top;
+ ErlOffHeap tmp_offheap;
if (old != 0) {
- erts_cleanup_offheap(&old->off_heap);
+ tmp_offheap.first = old->first_oh;
+ tmp_offheap.overhead = 0;
+ erts_cleanup_offheap(&tmp_offheap);
+ old->first_oh = tmp_offheap.first;
if (size == old->size) {
p = old;
} else {
@@ -2490,11 +2493,12 @@ void* db_get_term(DbTableCommon *tb, DbTerm* old, Uint offset, Eterm obj)
p = (DbTerm*) ((void *)(((char *) structp) + offset));
}
p->size = size;
- p->off_heap.first = NULL;
- p->off_heap.overhead = 0;
+ tmp_offheap.first = NULL;
+ tmp_offheap.overhead = 0;
top = DBTERM_BUF(p);
- copy = copy_struct(obj, size, &top, &p->off_heap);
+ copy = copy_struct(obj, size, &top, &tmp_offheap);
+ p->first_oh = tmp_offheap.first;
DBTERM_SET_TPL(p,tuple_val(copy));
return structp;
@@ -2503,7 +2507,10 @@ void* db_get_term(DbTableCommon *tb, DbTerm* old, Uint offset, Eterm obj)
void db_free_term_data(DbTerm* p)
{
- erts_cleanup_offheap(&p->off_heap);
+ ErlOffHeap tmp_offheap;
+ tmp_offheap.first = p->first_oh;
+ tmp_offheap.overhead = 0;
+ erts_cleanup_offheap(&tmp_offheap);
}
diff --git a/erts/emulator/beam/erl_db_util.h b/erts/emulator/beam/erl_db_util.h
index 672c5f2cd1..0f333e8b34 100644
--- a/erts/emulator/beam/erl_db_util.h
+++ b/erts/emulator/beam/erl_db_util.h
@@ -57,7 +57,7 @@
* A datatype for a database entry stored out of a process heap
*/
typedef struct db_term {
- ErlOffHeap off_heap; /* Off heap data for term. */
+ struct erl_off_heap_header* first_oh; /* Off heap data for term. */
Uint size; /* Size of term in "words" */
Eterm tpl[1]; /* Untagged "constant pointer" to top tuple */
/* (assumed to be first in buffer) */
diff --git a/erts/emulator/beam/erl_drv_thread.c b/erts/emulator/beam/erl_drv_thread.c
index d42820ddf3..17b08a71d4 100644
--- a/erts/emulator/beam/erl_drv_thread.c
+++ b/erts/emulator/beam/erl_drv_thread.c
@@ -528,7 +528,7 @@ erl_drv_tsd_get(ErlDrvTSDKey key)
if (!dtid)
return NULL;
#endif
- if (ERL_DRV_TSD_LEN__ < key)
+ if (ERL_DRV_TSD_LEN__ <= key)
return NULL;
return ERL_DRV_TSD__[key];
}
diff --git a/erts/emulator/beam/erl_fun.c b/erts/emulator/beam/erl_fun.c
index 5dce5ad262..84869f12d6 100644
--- a/erts/emulator/beam/erl_fun.c
+++ b/erts/emulator/beam/erl_fun.c
@@ -55,7 +55,7 @@ void
erts_init_fun_table(void)
{
HashFunctions f;
- erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_THR_OPTS_DEFAULT_INITER;
+ erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER;
rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ;
rwmtx_opt.lived = ERTS_SMP_RWMTX_LONG_LIVED;
diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c
index adc50675bf..0f4d2a2ef9 100644
--- a/erts/emulator/beam/erl_gc.c
+++ b/erts/emulator/beam/erl_gc.c
@@ -743,7 +743,10 @@ minor_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
* is large enough.
*/
- if (OLD_HEAP(p) && mature <= OLD_HEND(p) - OLD_HTOP(p)) {
+ if (OLD_HEAP(p) &&
+ ((mature <= OLD_HEND(p) - OLD_HTOP(p)) &&
+ ((BIN_VHEAP_MATURE(p) < ( BIN_OLD_VHEAP_SZ(p) - BIN_OLD_VHEAP(p)))) &&
+ ((BIN_OLD_VHEAP_SZ(p) > BIN_OLD_VHEAP(p))) ) ) {
ErlMessage *msgp;
Uint size_after;
Uint need_after;
@@ -1982,8 +1985,8 @@ shrink_new_heap(Process *p, Uint new_sz, Eterm *objv, int nobj)
HEAP_SIZE(p) = new_sz;
}
-static Uint
-do_next_vheap_size(Uint vheap, Uint vheap_sz) {
+static Uint64
+do_next_vheap_size(Uint64 vheap, Uint64 vheap_sz) {
/* grow
*
@@ -2000,27 +2003,33 @@ do_next_vheap_size(Uint vheap, Uint vheap_sz) {
* ----------------------
*/
- if (vheap > (Uint) (vheap_sz*3/4)) {
+ if ((Uint64) vheap/3 > (Uint64) (vheap_sz/4)) {
+ Uint64 new_vheap_sz = vheap_sz;
- while(vheap > (Uint) (vheap_sz*3/4)) {
- vheap_sz = vheap_sz*2;
+ while((Uint64) vheap/3 > (Uint64) (vheap_sz/4)) {
+ /* the golden ratio = 1.618 */
+ new_vheap_sz = (Uint64) vheap_sz * 1.618;
+ if (new_vheap_sz < vheap_sz ) {
+ return vheap_sz;
+ }
+ vheap_sz = new_vheap_sz;
}
- return erts_next_heap_size(vheap_sz, 0);
+ return vheap_sz;
}
- if (vheap < (Uint) (vheap_sz/4)) {
- return erts_next_heap_size((Uint) (vheap_sz / 2), 0);
+ if (vheap < (Uint64) (vheap_sz/4)) {
+ return (vheap_sz >> 1);
}
return vheap_sz;
}
-static Uint
-next_vheap_size(Process* p, Uint vheap, Uint vheap_sz) {
- vheap_sz = do_next_vheap_size(vheap, vheap_sz);
- return vheap_sz < p->min_vheap_size ? p->min_vheap_size : vheap_sz;
+static Uint64
+next_vheap_size(Process* p, Uint64 vheap, Uint64 vheap_sz) {
+ Uint64 new_vheap_sz = do_next_vheap_size(vheap, vheap_sz);
+ return new_vheap_sz < p->min_vheap_size ? p->min_vheap_size : new_vheap_sz;
}
struct shrink_cand_data {
@@ -2079,7 +2088,7 @@ link_live_proc_bin(struct shrink_cand_data *shrink,
}
-static void
+static void
sweep_off_heap(Process *p, int fullsweep)
{
struct shrink_cand_data shrink = {0};
@@ -2087,7 +2096,7 @@ sweep_off_heap(Process *p, int fullsweep)
struct erl_off_heap_header** prev;
char* oheap = NULL;
Uint oheap_sz = 0;
- Uint bin_vheap = 0;
+ Uint64 bin_vheap = 0;
#ifdef DEBUG
int seen_mature = 0;
#endif
@@ -2171,13 +2180,12 @@ sweep_off_heap(Process *p, int fullsweep)
}
}
- if (BIN_OLD_VHEAP(p) >= BIN_OLD_VHEAP_SZ(p)) {
- FLAGS(p) |= F_NEED_FULLSWEEP;
+ if (fullsweep) {
+ BIN_OLD_VHEAP_SZ(p) = next_vheap_size(p, BIN_OLD_VHEAP(p) + MSO(p).overhead, BIN_OLD_VHEAP_SZ(p));
}
-
- BIN_VHEAP_SZ(p) = next_vheap_size(p, bin_vheap, BIN_VHEAP_SZ(p));
- BIN_OLD_VHEAP_SZ(p) = next_vheap_size(p, BIN_OLD_VHEAP(p), BIN_OLD_VHEAP_SZ(p));
- MSO(p).overhead = bin_vheap;
+ BIN_VHEAP_SZ(p) = next_vheap_size(p, bin_vheap, BIN_VHEAP_SZ(p));
+ MSO(p).overhead = bin_vheap;
+ BIN_VHEAP_MATURE(p) = bin_vheap;
/*
* If we got any shrink candidates, check them out.
diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c
index 14bd10b42c..36fefc5cba 100644
--- a/erts/emulator/beam/erl_init.c
+++ b/erts/emulator/beam/erl_init.c
@@ -512,6 +512,8 @@ void erts_usage(void)
erts_fprintf(stderr, " u|ns|ts|ps|s|nnts|nnps|tnnps|db\n");
erts_fprintf(stderr, "-sct cput set cpu topology,\n");
erts_fprintf(stderr, " see the erl(1) documentation for more info.\n");
+ erts_fprintf(stderr, "-swt val set scheduler wakeup threshold, valid values are:\n");
+ erts_fprintf(stderr, " very_low|low|medium|high|very_high.\n");
erts_fprintf(stderr, "-sss size suggested stack size in kilo words for scheduler threads,\n");
erts_fprintf(stderr, " valid range is [%d-%d]\n",
ERTS_SCHED_THREAD_MIN_STACK_SIZE,
@@ -533,7 +535,8 @@ void erts_usage(void)
erts_fprintf(stderr, "-W<i|w> set error logger warnings mapping,\n");
erts_fprintf(stderr, " see error_logger documentation for details\n");
-
+ erts_fprintf(stderr, "-zdbbl size set the distribution buffer busy limit in kilobytes\n");
+ erts_fprintf(stderr, " valid range is [1-%d]\n", INT_MAX/1024);
erts_fprintf(stderr, "\n");
erts_fprintf(stderr, "Note that if the emulator is started with erlexec (typically\n");
erts_fprintf(stderr, "from the erl script), these flags should be specified with +.\n");
@@ -816,7 +819,7 @@ early_init(int *argc, char **argv) /*
erl_sys_args(argc, argv);
erts_ets_realloc_always_moves = 0;
-
+ erts_dist_buf_busy_limit = ERTS_DE_BUSY_LIMIT;
}
#ifndef ERTS_SMP
@@ -1176,10 +1179,20 @@ erl_start(int argc, char **argv)
}
else if (sys_strcmp("mrq", sub_param) == 0)
use_multi_run_queue = 1;
- else if (sys_strcmp("srq", sub_param) == 0)
- use_multi_run_queue = 0;
else if (sys_strcmp("nsp", sub_param) == 0)
erts_use_sender_punish = 0;
+ else if (sys_strcmp("srq", sub_param) == 0)
+ use_multi_run_queue = 0;
+ else if (sys_strcmp("wt", sub_param) == 0) {
+ arg = get_arg(sub_param+2, argv[i+1], &i);
+ if (erts_sched_set_wakeup_limit(arg) != 0) {
+ erts_fprintf(stderr, "scheduler wakeup threshold: %s\n",
+ arg);
+ erts_usage();
+ }
+ VERBOSE(DEBUG_SYSTEM,
+ ("scheduler wakup threshold: %s\n", arg));
+ }
else if (has_prefix("ss", sub_param)) {
/* suggested stack size (Kilo Words) for scheduler threads */
arg = get_arg(sub_param+2, argv[i+1], &i);
@@ -1334,6 +1347,26 @@ erl_start(int argc, char **argv)
}
break;
+ case 'z': {
+ char *sub_param = argv[i]+2;
+ int new_limit;
+
+ if (has_prefix("dbbl", sub_param)) {
+ arg = get_arg(sub_param+4, argv[i+1], &i);
+ new_limit = atoi(arg);
+ if (new_limit < 1 || INT_MAX/1024 < new_limit) {
+ erts_fprintf(stderr, "Invalid dbbl limit: %d\n", new_limit);
+ erts_usage();
+ } else {
+ erts_dist_buf_busy_limit = new_limit*1024;
+ }
+ } else {
+ erts_fprintf(stderr, "bad -z option %s\n", argv[i]);
+ erts_usage();
+ }
+ break;
+ }
+
default:
erts_fprintf(stderr, "%s unknown flag %s\n", argv[0], argv[i]);
erts_usage();
diff --git a/erts/emulator/beam/erl_lock_check.c b/erts/emulator/beam/erl_lock_check.c
index 99cc80e259..d6138fa4e4 100644
--- a/erts/emulator/beam/erl_lock_check.c
+++ b/erts/emulator/beam/erl_lock_check.c
@@ -1258,7 +1258,6 @@ erts_lc_init_lock(erts_lc_lock_t *lck, char *name, Uint16 flags)
{
lck->id = erts_lc_get_lock_order_id(name);
- /* XXX:PaN What to do with the extra information? */
lck->extra = make_boxed(&lck->extra);
lck->flags = flags;
lck->inited = ERTS_LC_INITITALIZED;
diff --git a/erts/emulator/beam/erl_message.c b/erts/emulator/beam/erl_message.c
index 1f61dca230..82f272d28a 100644
--- a/erts/emulator/beam/erl_message.c
+++ b/erts/emulator/beam/erl_message.c
@@ -220,7 +220,7 @@ link_mbuf_to_proc(Process *proc, ErlHeapFragment *bp)
*next_p = MSO(proc).first;
MSO(proc).first = bp->off_heap.first;
bp->off_heap.first = NULL;
- MSO(proc).overhead += bp->off_heap.overhead;
+ OH_OVERHEAD(&(MSO(proc)), bp->off_heap.overhead);
}
}
}
@@ -535,7 +535,7 @@ erts_move_msg_mbuf_to_heap(Eterm** hpp, ErlOffHeap* off_heap, ErlMessage *msg)
goto copy_done;
}
- off_heap->overhead += bp->off_heap.overhead;
+ OH_OVERHEAD(off_heap, bp->off_heap.overhead);
sz = bp->used_size;
ASSERT(is_immed(term) || in_heapfrag(ptr_val(term),bp));
diff --git a/erts/emulator/beam/erl_message.h b/erts/emulator/beam/erl_message.h
index 55ea92860a..5aca0db6fe 100644
--- a/erts/emulator/beam/erl_message.h
+++ b/erts/emulator/beam/erl_message.h
@@ -37,9 +37,13 @@ struct erl_off_heap_header {
struct erl_off_heap_header* next;
};
+#define OH_OVERHEAD(oh, size) do { \
+ (oh)->overhead += size; \
+} while(0)
+
typedef struct erl_off_heap {
struct erl_off_heap_header* first;
- int overhead; /* Administrative overhead (used to force GC). */
+ Uint64 overhead; /* Administrative overhead (used to force GC). */
} ErlOffHeap;
#include "external.h"
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c
index e95d9c4f75..1dd9c8bd4a 100644
--- a/erts/emulator/beam/erl_nif.c
+++ b/erts/emulator/beam/erl_nif.c
@@ -631,7 +631,7 @@ Eterm enif_make_binary(ErlNifEnv* env, ErlNifBinary* bin)
pb->bytes = (byte*) bptr->orig_bytes;
pb->flags = 0;
- MSO(env->proc).overhead += pb->size / sizeof(Eterm);
+ OH_OVERHEAD(&(MSO(env->proc)), pb->size / sizeof(Eterm));
bin_term = make_binary(pb);
if (erts_refc_read(&bptr->refc, 1) == 1) {
/* Total ownership transfer */
@@ -750,7 +750,19 @@ int enif_get_ulong(ErlNifEnv* env, Eterm term, unsigned long* ip)
#endif
}
-int enif_get_double(ErlNifEnv* env, Eterm term, double* dp)
+#if HAVE_INT64 && SIZEOF_LONG != 8
+int enif_get_int64(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifSInt64* ip)
+{
+ return term_to_Sint64(term, ip);
+}
+
+int enif_get_uint64(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifUInt64* ip)
+{
+ return term_to_Uint64(term, ip);
+}
+#endif /* HAVE_INT64 && SIZEOF_LONG != 8 */
+
+int enif_get_double(ErlNifEnv* env, ERL_NIF_TERM term, double* dp)
{
FloatDef f;
if (is_not_float(term)) {
@@ -817,6 +829,26 @@ ERL_NIF_TERM enif_make_ulong(ErlNifEnv* env, unsigned long i)
return IS_USMALL(0,i) ? make_small(i) : uint_to_big(i,alloc_heap(env,2));
}
+#if HAVE_INT64 && SIZEOF_LONG != 8
+ERL_NIF_TERM enif_make_int64(ErlNifEnv* env, ErlNifSInt64 i)
+{
+ Uint* hp;
+ Uint need = 0;
+ erts_bld_sint64(NULL, &need, i);
+ hp = alloc_heap(env, need);
+ return erts_bld_sint64(&hp, NULL, i);
+}
+
+ERL_NIF_TERM enif_make_uint64(ErlNifEnv* env, ErlNifUInt64 i)
+{
+ Uint* hp;
+ Uint need = 0;
+ erts_bld_uint64(NULL, &need, i);
+ hp = alloc_heap(env, need);
+ return erts_bld_uint64(&hp, NULL, i);
+}
+#endif /* HAVE_INT64 && SIZEOF_LONG != 8 */
+
ERL_NIF_TERM enif_make_double(ErlNifEnv* env, double d)
{
Eterm* hp = alloc_heap(env,FLOAT_SIZE_OBJECT);
diff --git a/erts/emulator/beam/erl_nif.h b/erts/emulator/beam/erl_nif.h
index 936f03bce1..ee3a7cd5f4 100644
--- a/erts/emulator/beam/erl_nif.h
+++ b/erts/emulator/beam/erl_nif.h
@@ -66,6 +66,19 @@
extern "C" {
#endif
+#if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_))
+typedef unsigned __int64 ErlNifUInt64;
+typedef __int64 ErlNifSInt64;
+#elif SIZEOF_LONG == 8
+typedef unsigned long ErlNifUInt64;
+typedef long ErlNifSInt64;
+#elif SIZEOF_LONG_LONG == 8
+typedef unsigned long long ErlNifUInt64;
+typedef long long ErlNifSInt64;
+#else
+#error No 64-bit integer type
+#endif
+
#ifdef HALFWORD_HEAP_EMULATOR
typedef unsigned int ERL_NIF_TERM;
#else
diff --git a/erts/emulator/beam/erl_nif_api_funcs.h b/erts/emulator/beam/erl_nif_api_funcs.h
index ef4e9580b0..eca506593d 100644
--- a/erts/emulator/beam/erl_nif_api_funcs.h
+++ b/erts/emulator/beam/erl_nif_api_funcs.h
@@ -122,6 +122,12 @@ ERL_NIF_API_FUNC_DECL(ErlNifPid*,enif_self,(ErlNifEnv* caller_env, ErlNifPid* pi
ERL_NIF_API_FUNC_DECL(int,enif_get_local_pid,(ErlNifEnv* env, ERL_NIF_TERM, ErlNifPid* pid));
ERL_NIF_API_FUNC_DECL(void,enif_keep_resource,(void* obj));
ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_resource_binary,(ErlNifEnv*,void* obj,const void* data, size_t size));
+#if SIZEOF_LONG != 8
+ERL_NIF_API_FUNC_DECL(int,enif_get_int64,(ErlNifEnv*, ERL_NIF_TERM term, ErlNifSInt64* ip));
+ERL_NIF_API_FUNC_DECL(int,enif_get_uint64,(ErlNifEnv*, ERL_NIF_TERM term, ErlNifUInt64* ip));
+ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_int64,(ErlNifEnv*, ErlNifSInt64));
+ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_uint64,(ErlNifEnv*, ErlNifUInt64));
+#endif
/*
** Add last to keep compatibility on Windows!!!
@@ -230,6 +236,13 @@ ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_resource_binary,(ErlNifEnv*,void* o
# define enif_get_local_pid ERL_NIF_API_FUNC_MACRO(enif_get_local_pid)
# define enif_keep_resource ERL_NIF_API_FUNC_MACRO(enif_keep_resource)
# define enif_make_resource_binary ERL_NIF_API_FUNC_MACRO(enif_make_resource_binary)
+#if SIZEOF_LONG != 8
+# define enif_get_int64 ERL_NIF_API_FUNC_MACRO(enif_get_int64)
+# define enif_get_uint64 ERL_NIF_API_FUNC_MACRO(enif_get_uint64)
+# define enif_make_int64 ERL_NIF_API_FUNC_MACRO(enif_make_int64)
+# define enif_make_uint64 ERL_NIF_API_FUNC_MACRO(enif_make_uint64)
+#endif
+
#endif
#ifndef enif_make_list1
@@ -253,5 +266,13 @@ ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_resource_binary,(ErlNifEnv*,void* o
# define enif_make_tuple9(ENV,E1,E2,E3,E4,E5,E6,E7,E8,E9) enif_make_tuple(ENV,9,E1,E2,E3,E4,E5,E6,E7,E8,E9)
# define enif_make_pid(ENV, PID) ((const ERL_NIF_TERM)((PID)->pid))
+
+#if SIZEOF_LONG == 8
+# define enif_get_int64 enif_get_long
+# define enif_get_uint64 enif_get_ulong
+# define enif_make_int64 enif_make_long
+# define enif_make_uint64 enif_make_ulong
+#endif
+
#endif
diff --git a/erts/emulator/beam/erl_node_tables.c b/erts/emulator/beam/erl_node_tables.c
index e430b4ad77..8cdda395df 100644
--- a/erts/emulator/beam/erl_node_tables.c
+++ b/erts/emulator/beam/erl_node_tables.c
@@ -80,7 +80,7 @@ dist_table_alloc(void *dep_tmpl)
Eterm chnl_nr;
Eterm sysname;
DistEntry *dep;
- erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_THR_OPTS_DEFAULT_INITER;
+ erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER;
rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ;
if(((DistEntry *) dep_tmpl) == erts_this_dist_entry)
@@ -107,7 +107,7 @@ dist_table_alloc(void *dep_tmpl)
dep->nlinks = NULL;
dep->monitors = NULL;
- erts_smp_spinlock_init_x(&dep->qlock, "dist_entry_out_queue", chnl_nr);
+ erts_smp_mtx_init_x(&dep->qlock, "dist_entry_out_queue", chnl_nr);
dep->qflgs = 0;
dep->qsize = 0;
dep->out_queue.first = NULL;
@@ -172,7 +172,7 @@ dist_table_free(void *vdep)
ASSERT(!dep->cache);
erts_smp_rwmtx_destroy(&dep->rwmtx);
erts_smp_mtx_destroy(&dep->lnk_mtx);
- erts_smp_spinlock_destroy(&dep->qlock);
+ erts_smp_mtx_destroy(&dep->qlock);
#ifdef DEBUG
sys_memset(vdep, 0x77, sizeof(DistEntry));
@@ -710,7 +710,7 @@ erts_set_this_node(Eterm sysname, Uint creation)
void erts_init_node_tables(void)
{
- erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_THR_OPTS_DEFAULT_INITER;
+ erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER;
HashFunctions f;
rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ;
@@ -755,9 +755,9 @@ void erts_init_node_tables(void)
erts_this_dist_entry->nlinks = NULL;
erts_this_dist_entry->monitors = NULL;
- erts_smp_spinlock_init_x(&erts_this_dist_entry->qlock,
- "dist_entry_out_queue",
- make_small(ERST_INTERNAL_CHANNEL_NO));
+ erts_smp_mtx_init_x(&erts_this_dist_entry->qlock,
+ "dist_entry_out_queue",
+ make_small(ERST_INTERNAL_CHANNEL_NO));
erts_this_dist_entry->qflgs = 0;
erts_this_dist_entry->qsize = 0;
erts_this_dist_entry->out_queue.first = NULL;
diff --git a/erts/emulator/beam/erl_node_tables.h b/erts/emulator/beam/erl_node_tables.h
index eb759b87e9..b0a63ae035 100644
--- a/erts/emulator/beam/erl_node_tables.h
+++ b/erts/emulator/beam/erl_node_tables.h
@@ -131,7 +131,7 @@ typedef struct dist_entry_ {
ErtsLink *nlinks; /* Link tree with subtrees */
ErtsMonitor *monitors; /* Monitor tree */
- erts_smp_spinlock_t qlock; /* Protects qflgs and out_queue */
+ erts_smp_mtx_t qlock; /* Protects qflgs and out_queue */
Uint32 qflgs;
Sint qsize;
ErtsDistOutputQueue out_queue;
diff --git a/erts/emulator/beam/erl_obsolete.c b/erts/emulator/beam/erl_obsolete.c
deleted file mode 100644
index 9c5a7c7ff9..0000000000
--- a/erts/emulator/beam/erl_obsolete.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * %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%
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "sys.h"
-#include "erl_driver.h"
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
- * *
- * ------------------------- OBSOLETE! DO NOT USE! ------------------------- *
- * *
-\* */
-
-/* cut from ../obsolete/driver.h (since it doesn't mix well with other
- * headers from the emulator).
- */
-#ifdef __WIN32__
-#ifdef CONST
-# undef CONST
-#endif
-#endif
-
-#if ((defined(__STDC__) || defined(SABER)) && !defined(NO_PROTOTYPE)) || defined(__cplusplus) || defined(USE_PROTOTYPE)
-# define _USING_PROTOTYPES_ 1
-# define _ANSI_ARGS_(x) x
-# define CONST const
-#else
-# define _ANSI_ARGS_(x) ()
-# define CONST
-#endif
-
-typedef void* erl_mutex_t;
-typedef void* erl_cond_t;
-typedef void* erl_thread_t;
-
-EXTERN erl_mutex_t erts_mutex_create _ANSI_ARGS_((void));
-EXTERN int erts_mutex_destroy _ANSI_ARGS_((erl_mutex_t));
-EXTERN int erts_mutex_lock _ANSI_ARGS_((erl_mutex_t));
-EXTERN int erts_mutex_unlock _ANSI_ARGS_((erl_mutex_t));
-
-EXTERN erl_cond_t erts_cond_create _ANSI_ARGS_((void));
-EXTERN int erts_cond_destroy _ANSI_ARGS_((erl_cond_t));
-EXTERN int erts_cond_signal _ANSI_ARGS_((erl_cond_t));
-EXTERN int erts_cond_broadcast _ANSI_ARGS_((erl_cond_t));
-EXTERN int erts_cond_wait _ANSI_ARGS_((erl_cond_t, erl_mutex_t));
-EXTERN int erts_cond_timedwait _ANSI_ARGS_((erl_cond_t, erl_mutex_t, long));
-
-EXTERN int erts_thread_create _ANSI_ARGS_((erl_thread_t*,
- void* (*func)(void*),
- void* arg,
- int detached));
-EXTERN erl_thread_t erts_thread_self _ANSI_ARGS_((void));
-EXTERN void erts_thread_exit _ANSI_ARGS_((void*));
-EXTERN int erts_thread_join _ANSI_ARGS_((erl_thread_t, void**));
-EXTERN int erts_thread_kill _ANSI_ARGS_((erl_thread_t));
-
-/*
- * These functions implement the thread interface in ../obsolete/driver.h.
- * Do *not* use this interface! Within the emulator, use the erl_threads.h,
- * erl_smp.h, or ethread.h interface. From a driver use the thread interface
- * in erl_driver.h.
- */
-
-erl_mutex_t
-erts_mutex_create(void)
-{
- return (erl_mutex_t) erl_drv_mutex_create(NULL);
-}
-
-int
-erts_mutex_destroy(erl_mutex_t mtx)
-{
- erl_drv_mutex_destroy((ErlDrvMutex *) mtx);
- return 0;
-}
-
-int
-erts_mutex_lock(erl_mutex_t mtx)
-{
- erl_drv_mutex_lock((ErlDrvMutex *) mtx);
- return 0;
-}
-
-int
-erts_mutex_unlock(erl_mutex_t mtx)
-{
- erl_drv_mutex_unlock((ErlDrvMutex *) mtx);
- return 0;
-}
-
-erl_cond_t
-erts_cond_create(void)
-{
- return (erl_cond_t) erl_drv_cond_create(NULL);
-}
-
-int
-erts_cond_destroy(erl_cond_t cnd)
-{
- erl_drv_cond_destroy((ErlDrvCond *) cnd);
- return 0;
-}
-
-
-int
-erts_cond_signal(erl_cond_t cnd)
-{
- erl_drv_cond_signal((ErlDrvCond *) cnd);
- return 0;
-}
-
-int
-erts_cond_broadcast(erl_cond_t cnd)
-{
- erl_drv_cond_broadcast((ErlDrvCond *) cnd);
- return 0;
-}
-
-
-int
-erts_cond_wait(erl_cond_t cnd, erl_mutex_t mtx)
-{
- erl_drv_cond_wait((ErlDrvCond *) cnd, (ErlDrvMutex *) mtx);
- return 0;
-}
-
-int
-erts_cond_timedwait(erl_cond_t cnd, erl_mutex_t mtx, long ms)
-{
- return ENOTSUP;
-}
-
-int
-erts_thread_create(erl_thread_t *tid,
- void* (*func)(void*),
- void* arg,
- int detached)
-{
- if (detached)
- return ENOTSUP;
- return erl_drv_thread_create(NULL, (ErlDrvTid *) tid, func, arg, NULL);
-}
-
-erl_thread_t
-erts_thread_self(void)
-{
- return (erl_thread_t) erl_drv_thread_self();
-}
-
-void
-erts_thread_exit(void *res)
-{
- erl_drv_thread_exit(res);
-}
-
-int
-erts_thread_join(erl_thread_t tid, void **respp)
-{
- return erl_drv_thread_join((ErlDrvTid) tid, respp);
-}
-
-int
-erts_thread_kill(erl_thread_t tid)
-{
- return ENOTSUP;
-}
-
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index 0dfcfa2c63..799f1a3cc9 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -54,7 +54,12 @@
(ERTS_SCHED_SYS_SLEEP_SPINCOUNT*ERTS_SCHED_TSE_SLEEP_SPINCOUNT_FACT)
#define ERTS_SCHED_SUSPEND_SLEEP_SPINCOUNT 0
-#define ERTS_WAKEUP_OTHER_LIMIT (100*CONTEXT_REDS/2)
+#define ERTS_WAKEUP_OTHER_LIMIT_VERY_HIGH (200*CONTEXT_REDS)
+#define ERTS_WAKEUP_OTHER_LIMIT_HIGH (50*CONTEXT_REDS)
+#define ERTS_WAKEUP_OTHER_LIMIT_MEDIUM (10*CONTEXT_REDS)
+#define ERTS_WAKEUP_OTHER_LIMIT_LOW (CONTEXT_REDS)
+#define ERTS_WAKEUP_OTHER_LIMIT_VERY_LOW (CONTEXT_REDS/10)
+
#define ERTS_WAKEUP_OTHER_DEC 10
#define ERTS_WAKEUP_OTHER_FIXED_INC (CONTEXT_REDS/10)
@@ -112,6 +117,8 @@ Uint erts_no_schedulers;
Uint erts_max_processes = ERTS_DEFAULT_MAX_PROCESSES;
Uint erts_process_tab_index_mask;
+static int wakeup_other_limit;
+
#ifdef ERTS_SMP
Uint erts_max_main_threads;
#endif
@@ -821,7 +828,11 @@ empty_runq(ErtsRunQueue *rq)
if (oifls & ERTS_RUNQ_IFLG_NONEMPTY) {
#ifdef DEBUG
long empty = erts_smp_atomic_read(&no_empty_run_queues);
- ASSERT(0 <= empty && empty < erts_no_run_queues);
+ /*
+ * For a short period of time no_empty_run_queues may have
+ * been increased twice for a specific run queue.
+ */
+ ASSERT(0 <= empty && empty < 2*erts_no_run_queues);
#endif
erts_smp_atomic_inc(&no_empty_run_queues);
}
@@ -834,7 +845,11 @@ non_empty_runq(ErtsRunQueue *rq)
if (!(oifls & ERTS_RUNQ_IFLG_NONEMPTY)) {
#ifdef DEBUG
long empty = erts_smp_atomic_read(&no_empty_run_queues);
- ASSERT(0 < empty && empty <= erts_no_run_queues);
+ /*
+ * For a short period of time no_empty_run_queues may have
+ * been increased twice for a specific run queue.
+ */
+ ASSERT(0 < empty && empty <= 2*erts_no_run_queues);
#endif
erts_smp_atomic_dec(&no_empty_run_queues);
}
@@ -2369,8 +2384,28 @@ void
erts_early_init_scheduling(void)
{
early_cpu_bind_init();
+ wakeup_other_limit = ERTS_WAKEUP_OTHER_LIMIT_MEDIUM;
}
+int
+erts_sched_set_wakeup_limit(char *str)
+{
+ if (sys_strcmp(str, "very_high") == 0)
+ wakeup_other_limit = ERTS_WAKEUP_OTHER_LIMIT_VERY_HIGH;
+ else if (sys_strcmp(str, "high") == 0)
+ wakeup_other_limit = ERTS_WAKEUP_OTHER_LIMIT_HIGH;
+ else if (sys_strcmp(str, "medium") == 0)
+ wakeup_other_limit = ERTS_WAKEUP_OTHER_LIMIT_MEDIUM;
+ else if (sys_strcmp(str, "low") == 0)
+ wakeup_other_limit = ERTS_WAKEUP_OTHER_LIMIT_LOW;
+ else if (sys_strcmp(str, "very_low") == 0)
+ wakeup_other_limit = ERTS_WAKEUP_OTHER_LIMIT_VERY_LOW;
+ else
+ return EINVAL;
+ return 0;
+}
+
+
void
erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online)
{
@@ -2497,9 +2532,9 @@ erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online)
aligned_sched_sleep_info = erts_alloc(ERTS_ALC_T_SCHDLR_SLP_INFO,
(sizeof(ErtsAlignedSchedulerSleepInfo)
*(n+1)));
- if ((((Uint) aligned_sched_sleep_info) & ERTS_CACHE_LINE_MASK) == 0)
+ if ((((UWord) aligned_sched_sleep_info) & ERTS_CACHE_LINE_MASK) == 0)
aligned_sched_sleep_info = ((ErtsAlignedSchedulerSleepInfo *)
- ((((Uint) aligned_sched_sleep_info)
+ ((((UWord) aligned_sched_sleep_info)
& ~ERTS_CACHE_LINE_MASK)
+ ERTS_CACHE_LINE_SIZE));
for (ix = 0; ix < n; ix++) {
@@ -3966,13 +4001,13 @@ check_cpu_bind(ErtsSchedulerData *esdp)
goto unbind;
}
}
- else if (cpu_id < 0 && scheduler2cpu_map[esdp->no].bound_id >= 0) {
+ else if (cpu_id < 0) {
unbind:
/* Get rid of old binding */
res = erts_unbind_from_cpu(erts_cpuinfo);
if (res == 0)
esdp->cpu_id = scheduler2cpu_map[esdp->no].bound_id = -1;
- else {
+ else if (res != -ENOTSUP) {
erts_dsprintf_buf_t *dsbufp = erts_create_logger_dsbuf();
erts_dsprintf(dsbufp, "Scheduler %d failed to unbind from cpu %d: %s\n",
(int) esdp->no, cpu_id, erl_errno_id(-res));
@@ -4005,7 +4040,7 @@ signal_schedulers_bind_change(erts_cpu_topology_t *cpudata, int size)
int s_ix = 1;
int cpu_ix;
- if (cpu_bind_order != ERTS_CPU_BIND_NONE) {
+ if (cpu_bind_order != ERTS_CPU_BIND_NONE && size) {
cpu_bind_order_sort(cpudata, size, cpu_bind_order, 1);
@@ -5519,12 +5554,50 @@ late_cpu_bind_init(void)
erts_cpu_topology_t *cpudata;
int cpudata_size;
create_tmp_cpu_topology_copy(&cpudata, &cpudata_size);
- ASSERT(cpudata);
signal_schedulers_bind_change(cpudata, cpudata_size);
destroy_tmp_cpu_topology_copy(cpudata);
}
}
+int
+erts_update_cpu_info(void)
+{
+ int changed;
+ erts_smp_rwmtx_rwlock(&erts_cpu_bind_rwmtx);
+ changed = erts_cpu_info_update(erts_cpuinfo);
+ if (changed) {
+ erts_cpu_topology_t *cpudata;
+ int cpudata_size;
+
+ if (system_cpudata)
+ erts_free(ERTS_ALC_T_CPUDATA, system_cpudata);
+
+ system_cpudata_size = erts_get_cpu_topology_size(erts_cpuinfo);
+ if (!system_cpudata_size)
+ system_cpudata = NULL;
+ else {
+ system_cpudata = erts_alloc(ERTS_ALC_T_CPUDATA,
+ (sizeof(erts_cpu_topology_t)
+ * system_cpudata_size));
+
+ if (!erts_get_cpu_topology(erts_cpuinfo, system_cpudata)
+ || (ERTS_INIT_CPU_TOPOLOGY_OK
+ != verify_topology(system_cpudata,
+ system_cpudata_size))) {
+ erts_free(ERTS_ALC_T_CPUDATA, system_cpudata);
+ system_cpudata = NULL;
+ system_cpudata_size = 0;
+ }
+ }
+
+ create_tmp_cpu_topology_copy(&cpudata, &cpudata_size);
+ signal_schedulers_bind_change(cpudata, cpudata_size);
+ destroy_tmp_cpu_topology_copy(cpudata);
+ }
+ erts_smp_rwmtx_rwunlock(&erts_cpu_bind_rwmtx);
+ return changed;
+}
+
#ifdef ERTS_SMP
static void
@@ -7129,7 +7202,7 @@ Process *schedule(Process *p, int calls)
if (rq->wakeup_other < 0)
rq->wakeup_other = 0;
}
- else if (rq->wakeup_other < ERTS_WAKEUP_OTHER_LIMIT)
+ else if (rq->wakeup_other < wakeup_other_limit)
rq->wakeup_other += rq->len*wo_reds + ERTS_WAKEUP_OTHER_FIXED_INC;
else {
if (erts_common_run_queue) {
@@ -7430,6 +7503,15 @@ erts_schedule_misc_op(void (*func)(void *), void *arg)
ErtsRunQueue *rq = erts_get_runq_current(NULL);
ErtsMiscOpList *molp = misc_op_list_alloc();
+ if (!rq) {
+ /*
+ * This can only happen when the sys msg dispatcher
+ * thread schedules misc ops (this happens *very*
+ * seldom; only when trace drivers are unloaded).
+ */
+ rq = ERTS_RUNQ_IX(0);
+ }
+
erts_smp_runq_lock(rq);
while (rq->misc.evac_runq) {
@@ -7805,6 +7887,7 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
p->bin_vheap_sz = p->min_vheap_size;
p->bin_old_vheap_sz = p->min_vheap_size;
p->bin_old_vheap = 0;
+ p->bin_vheap_mature = 0;
/* No need to initialize p->fcalls. */
@@ -8057,6 +8140,7 @@ void erts_init_empty_process(Process *p)
p->bin_vheap_sz = BIN_VH_MIN_SIZE;
p->bin_old_vheap_sz = BIN_VH_MIN_SIZE;
p->bin_old_vheap = 0;
+ p->bin_vheap_mature = 0;
#ifdef ERTS_SMP
p->u.ptimer = NULL;
p->bound_runq = NULL;
diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h
index c3fef6d38e..4365e409e5 100644
--- a/erts/emulator/beam/erl_process.h
+++ b/erts/emulator/beam/erl_process.h
@@ -537,6 +537,7 @@ struct ErtsPendingSuspend_ {
# define MIN_VHEAP_SIZE(p) (p)->min_vheap_size
# define BIN_VHEAP_SZ(p) (p)->bin_vheap_sz
+# define BIN_VHEAP_MATURE(p) (p)->bin_vheap_mature
# define BIN_OLD_VHEAP_SZ(p) (p)->bin_old_vheap_sz
# define BIN_OLD_VHEAP(p) (p)->bin_old_vheap
@@ -654,9 +655,10 @@ struct process {
Uint mbuf_sz; /* Size of all message buffers */
ErtsPSD *psd; /* Rarely used process specific data */
- Uint bin_vheap_sz; /* Virtual heap block size for binaries */
- Uint bin_old_vheap_sz; /* Virtual old heap block size for binaries */
- Uint bin_old_vheap; /* Virtual old heap size for binaries */
+ Uint64 bin_vheap_sz; /* Virtual heap block size for binaries */
+ Uint64 bin_vheap_mature; /* Virtual heap block size for binaries */
+ Uint64 bin_old_vheap_sz; /* Virtual old heap block size for binaries */
+ Uint64 bin_old_vheap; /* Virtual old heap size for binaries */
union {
#ifdef ERTS_SMP
@@ -1025,6 +1027,7 @@ int erts_init_scheduler_bind_type(char *how);
#define ERTS_INIT_CPU_TOPOLOGY_MISSING 9
int erts_init_cpu_topology(char *topology_str);
+int erts_update_cpu_info(void);
void erts_pre_init_process(void);
void erts_late_init_process(void);
@@ -1035,6 +1038,8 @@ ErtsProcList *erts_proclist_create(Process *);
void erts_proclist_destroy(ErtsProcList *);
int erts_proclist_same(ErtsProcList *, Process *);
+int erts_sched_set_wakeup_limit(char *str);
+
#ifdef DEBUG
void erts_dbg_multi_scheduling_return_trap(Process *, Eterm);
#endif
diff --git a/erts/emulator/beam/erl_time_sup.c b/erts/emulator/beam/erl_time_sup.c
index c15f85f8f1..7b8706ea13 100644
--- a/erts/emulator/beam/erl_time_sup.c
+++ b/erts/emulator/beam/erl_time_sup.c
@@ -650,6 +650,22 @@ local_to_univ(Sint *year, Sint *month, Sint *day,
t.tm_sec = *second;
t.tm_isdst = isdst;
the_clock = mktime(&t);
+ if (the_clock == -1) {
+ if (isdst) {
+ /* If this is a timezone without DST and the OS (correctly)
+ refuses to give us a DST time, we simulate the Linux/Solaris
+ behaviour of giving the same data as if is_dst was not set. */
+ t.tm_isdst = 0;
+ the_clock = mktime(&t);
+ if (the_clock == -1) {
+ /* Failed anyway, something else is bad - will be a badarg */
+ return 0;
+ }
+ } else {
+ /* Something else is the matter, badarg. */
+ return 0;
+ }
+ }
#ifdef HAVE_GMTIME_R
gmtime_r(&the_clock, (tm = &tmbuf));
#else
@@ -663,6 +679,10 @@ local_to_univ(Sint *year, Sint *month, Sint *day,
*second = tm->tm_sec;
return 1;
}
+#if defined(HAVE_POSIX2TIME) && defined(HAVE_DECL_POSIX2TIME) && \
+ !HAVE_DECL_POSIX2TIME
+extern time_t posix2time(time_t);
+#endif
int
univ_to_local(Sint *year, Sint *month, Sint *day,
diff --git a/erts/emulator/beam/export.c b/erts/emulator/beam/export.c
index 5e81a2d624..5bc402fe22 100644
--- a/erts/emulator/beam/export.c
+++ b/erts/emulator/beam/export.c
@@ -109,7 +109,7 @@ void
init_export_table(void)
{
HashFunctions f;
- erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_THR_OPTS_DEFAULT_INITER;
+ erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER;
rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ;
rwmtx_opt.lived = ERTS_SMP_RWMTX_LONG_LIVED;
diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h
index 064dc69da8..ecd3c8f68a 100644
--- a/erts/emulator/beam/global.h
+++ b/erts/emulator/beam/global.h
@@ -1026,7 +1026,7 @@ void print_pass_through(int, byte*, int);
/* beam_emu.c */
int catchlevel(Process*);
-void init_emulator(_VOID_);
+void init_emulator(void);
void process_main(void);
Eterm build_stacktrace(Process* c_p, Eterm exc);
Eterm expand_error_value(Process* c_p, Uint freason, Eterm Value);
@@ -1499,7 +1499,7 @@ erts_cmp_timeval(SysTimeval *t1p, SysTimeval *t2p)
#endif
#ifdef DEBUG
-void p_slpq(_VOID_);
+void p_slpq(void);
#endif
/* utils.c */
@@ -1686,7 +1686,7 @@ int io_list_to_buf(Eterm, char*, int);
int io_list_to_buf2(Eterm, char*, int);
int io_list_len(Eterm);
int is_string(Eterm);
-void erl_at_exit(FUNCTION(void,(*),(void*)), void*);
+void erl_at_exit(void (*) (void*), void*);
Eterm collect_memory(Process *);
void dump_memory_to_fd(int);
int dump_memory_data(const char *);
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c
index b840f65cdd..9ed92bbe03 100644
--- a/erts/emulator/beam/io.c
+++ b/erts/emulator/beam/io.c
@@ -1582,7 +1582,7 @@ static void deliver_read_message(Port* prt, Eterm to,
pb->flags = 0;
hp += PROC_BIN_SIZE;
- ohp->overhead += pb->size / sizeof(Eterm);
+ OH_OVERHEAD(ohp, pb->size / sizeof(Eterm));
listp = make_binary(pb);
}
@@ -1732,7 +1732,7 @@ deliver_vec_message(Port* prt, /* Port */
pb->flags = 0;
hp += PROC_BIN_SIZE;
- ohp->overhead += iov->iov_len / sizeof(Eterm);
+ OH_OVERHEAD(ohp, iov->iov_len / sizeof(Eterm));
if (listp == NIL) { /* compatible with deliver_bin_message */
listp = make_binary(pb);
@@ -2264,7 +2264,7 @@ erts_port_control(Process* p, Port* prt, Uint command, Eterm iolist)
pb->val = ErlDrvBinary2Binary(dbin);
pb->bytes = (byte*) dbin->orig_bytes;
pb->flags = 0;
- MSO(p).overhead += dbin->orig_size / sizeof(Eterm);
+ OH_OVERHEAD(&(MSO(p)), dbin->orig_size / sizeof(Eterm));
return make_binary(pb);
}
port_resp = dbin->orig_bytes;
@@ -2802,17 +2802,25 @@ driver_deliver_term(ErlDrvPort port,
break;
case ERL_DRV_INT: /* signed int argument */
ERTS_DDT_CHK_ENOUGH_ARGS(1);
+#if HALFWORD_HEAP
+ erts_bld_sint64(NULL, &need, (Sint64)ptr[0]);
+#else
/* check for bignum */
if (!IS_SSMALL((Sint)ptr[0]))
need += BIG_UINT_HEAP_SIZE; /* use small_to_big */
+#endif
ptr++;
depth++;
break;
case ERL_DRV_UINT: /* unsigned int argument */
ERTS_DDT_CHK_ENOUGH_ARGS(1);
+#if HALFWORD_HEAP
+ erts_bld_uint64(NULL, &need, (Uint64)ptr[0]);
+#else
/* check for bignum */
if (!IS_USMALL(0, (Uint)ptr[0]))
need += BIG_UINT_HEAP_SIZE; /* use small_to_big */
+#endif
ptr++;
depth++;
break;
@@ -2979,22 +2987,30 @@ driver_deliver_term(ErlDrvPort port,
break;
case ERL_DRV_INT: /* signed int argument */
+#if HALFWORD_HEAP
+ mess = erts_bld_sint64(&hp, NULL, (Sint64)ptr[0]);
+#else
if (IS_SSMALL((Sint)ptr[0]))
mess = make_small((Sint)ptr[0]);
else {
mess = small_to_big((Sint)ptr[0], hp);
hp += BIG_UINT_HEAP_SIZE;
}
+#endif
ptr++;
break;
case ERL_DRV_UINT: /* unsigned int argument */
+#if HALFWORD_HEAP
+ mess = erts_bld_uint64(&hp, NULL, (Uint64)ptr[0]);
+#else
if (IS_USMALL(0, (Uint)ptr[0]))
mess = make_small((Uint)ptr[0]);
else {
mess = uint_to_big((Uint)ptr[0], hp);
hp += BIG_UINT_HEAP_SIZE;
}
+#endif
ptr++;
break;
@@ -3040,7 +3056,7 @@ driver_deliver_term(ErlDrvPort port,
pb->flags = 0;
mess = make_binary(pb);
hp += PROC_BIN_SIZE;
- ohp->overhead += pb->size / sizeof(Eterm);
+ OH_OVERHEAD(ohp, pb->size / sizeof(Eterm));
}
ptr += 3;
break;
@@ -3077,7 +3093,7 @@ driver_deliver_term(ErlDrvPort port,
pbp->val = bp;
pbp->bytes = (byte*) bp->orig_bytes;
pbp->flags = 0;
- ohp->overhead += (pbp->size / sizeof(Eterm));
+ OH_OVERHEAD(ohp, pbp->size / sizeof(Eterm));
mess = make_binary(pbp);
}
ptr += 2;
diff --git a/erts/emulator/beam/register.c b/erts/emulator/beam/register.c
index c9bb7bbe91..26d64887d0 100644
--- a/erts/emulator/beam/register.c
+++ b/erts/emulator/beam/register.c
@@ -145,7 +145,7 @@ static void reg_free(RegProc *obj)
void init_register_table(void)
{
HashFunctions f;
- erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_THR_OPTS_DEFAULT_INITER;
+ erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER;
rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ;
rwmtx_opt.lived = ERTS_SMP_RWMTX_LONG_LIVED;
diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h
index eac38674e7..0031568af6 100644
--- a/erts/emulator/beam/sys.h
+++ b/erts/emulator/beam/sys.h
@@ -25,14 +25,6 @@
# define NO_FPE_SIGNALS
#endif
-/* Never use elib-malloc when purify-memory-tracing */
-#if defined(PURIFY)
-#undef ENABLE_ELIB_MALLOC
-#undef ELIB_HEAP_SBRK
-#undef ELIB_ALLOC_IS_CLIB
-#endif
-
-
/* xxxP __VXWORKS__ */
#ifdef VXWORKS
#include <vxWorks.h>
@@ -171,23 +163,6 @@ void erl_assert_error(char* expr, char* file, int line);
#include <stdarg.h>
-#if defined(__STDC__) || defined(_MSC_VER)
-# define EXTERN_FUNCTION(t, f, x) extern t f x
-# define FUNCTION(t, f, x) t f x
-# define _DOTS_ ...
-# define _VOID_ void
-#elif defined(__cplusplus)
-# define EXTERN_FUNCTION(f, x) extern "C" { f x }
-# define FUNCTION(t, f, x) t f x
-# define _DOTS_ ...
-# define _VOID_ void
-#else
-# define EXTERN_FUNCTION(t, f, x) extern t f (/*x*/)
-# define FUNCTION(t, f, x) t f (/*x*/)
-# define _DOTS_
-# define _VOID_
-#endif
-
/* This isn't sys-dependent, but putting it here benefits sys.c and drivers
- allow use of 'const' regardless of compiler */
@@ -197,7 +172,7 @@ void erl_assert_error(char* expr, char* file, int line);
#ifdef VXWORKS
/* Replace VxWorks' printf with a real one that does fprintf(stdout, ...) */
-EXTERN_FUNCTION(int, real_printf, (const char *fmt, ...));
+int real_printf(const char *fmt, ...);
# define printf real_printf
#endif
@@ -660,12 +635,12 @@ extern void erl_sys_args(int *argc, char **argv);
extern void erl_sys_schedule(int);
void sys_tty_reset(int);
-EXTERN_FUNCTION(int, sys_max_files, (_VOID_));
+int sys_max_files(void);
void sys_init_io(void);
Preload* sys_preloaded(void);
-EXTERN_FUNCTION(unsigned char*, sys_preload_begin, (Preload*));
-EXTERN_FUNCTION(void, sys_preload_end, (Preload*));
-EXTERN_FUNCTION(int, sys_get_key, (int));
+unsigned char* sys_preload_begin(Preload*);
+void sys_preload_end(Preload*);
+int sys_get_key(int);
void elapsed_time_both(unsigned long *ms_user, unsigned long *ms_sys,
unsigned long *ms_user_diff, unsigned long *ms_sys_diff);
void wall_clock_elapsed_time_both(unsigned long *ms_total,
@@ -682,7 +657,7 @@ int local_to_univ(Sint *year, Sint *month, Sint *day,
Sint *hour, Sint *minute, Sint *second, int isdst);
void get_now(Uint*, Uint*, Uint*);
void get_sys_now(Uint*, Uint*, Uint*);
-EXTERN_FUNCTION(void, set_break_quit, (void (*)(void), void (*)(void)));
+void set_break_quit(void (*)(void), void (*)(void));
void os_flavor(char*, unsigned);
void os_version(int*, int*, int*);
@@ -722,7 +697,7 @@ int erts_write_env(char *key, char *value);
#define ERTS_DEFAULT_MMAP_THRESHOLD (128 * 1024)
#define ERTS_DEFAULT_MMAP_MAX 64
-EXTERN_FUNCTION(int, sys_alloc_opt, (int, int));
+int sys_alloc_opt(int, int);
typedef struct {
Sint trim_threshold;
@@ -731,7 +706,7 @@ typedef struct {
Sint mmap_max;
} SysAllocStat;
-EXTERN_FUNCTION(void, sys_alloc_stat, (SysAllocStat *));
+void sys_alloc_stat(SysAllocStat *);
/* Block the whole system... */
@@ -1120,13 +1095,10 @@ erts_refc_read(erts_refc_t *refcp, long min_val)
extern int erts_use_kernel_poll;
#endif
-void elib_ensure_initialized(void);
-
-
#if defined(VXWORKS)
/* NOTE! sys_calloc2 does not exist on other
platforms than VxWorks and OSE */
-EXTERN_FUNCTION(void*, sys_calloc2, (Uint, Uint));
+void* sys_calloc2(Uint, Uint);
#endif /* VXWORKS || OSE */
@@ -1218,8 +1190,8 @@ EXTERN_FUNCTION(void*, sys_calloc2, (Uint, Uint));
*/
#ifdef DEBUG
-EXTERN_FUNCTION(void, erl_debug, (char* format, ...));
-EXTERN_FUNCTION(void, erl_bin_write, (unsigned char *, int, int));
+void erl_debug(char* format, ...);
+void erl_bin_write(unsigned char *, int, int);
# define DEBUGF(x) erl_debug x
#else
diff --git a/erts/emulator/beam/time.c b/erts/emulator/beam/time.c
index a07d6a5327..53d39aef0e 100644
--- a/erts/emulator/beam/time.c
+++ b/erts/emulator/beam/time.c
@@ -83,24 +83,8 @@
#define ASSERT_NO_LOCKED_LOCKS
#endif
+static erts_smp_mtx_t tiw_lock;
-#if defined(ERTS_TIMER_THREAD) || 1
-/* I don't yet know why, but using a mutex instead of a spinlock
- or spin-based rwlock avoids excessive delays at startup. */
-static erts_smp_rwmtx_t tiw_lock;
-#define tiw_read_lock() erts_smp_rwmtx_rlock(&tiw_lock)
-#define tiw_read_unlock() erts_smp_rwmtx_runlock(&tiw_lock)
-#define tiw_write_lock() erts_smp_rwmtx_rwlock(&tiw_lock)
-#define tiw_write_unlock() erts_smp_rwmtx_rwunlock(&tiw_lock)
-#define tiw_init_lock() erts_smp_rwmtx_init(&tiw_lock, "timer_wheel")
-#else
-static erts_smp_rwlock_t tiw_lock;
-#define tiw_read_lock() erts_smp_read_lock(&tiw_lock)
-#define tiw_read_unlock() erts_smp_read_unlock(&tiw_lock)
-#define tiw_write_lock() erts_smp_write_lock(&tiw_lock)
-#define tiw_write_unlock() erts_smp_write_unlock(&tiw_lock)
-#define tiw_init_lock() erts_smp_rwlock_init(&tiw_lock, "timer_wheel")
-#endif
/* BEGIN tiw_lock protected variables
**
@@ -224,10 +208,10 @@ int next_time(void)
{
int ret;
- tiw_write_lock();
+ erts_smp_mtx_lock(&tiw_lock);
(void)do_time_update();
ret = next_time_internal();
- tiw_write_unlock();
+ erts_smp_mtx_unlock(&tiw_lock);
return ret;
}
#endif
@@ -241,7 +225,7 @@ static ERTS_INLINE void bump_timer_internal(long dt) /* PRE: tiw_lock is write-l
/* no need to bump the position if there aren't any timeouts */
if (tiw_nto == 0) {
- tiw_write_unlock();
+ erts_smp_mtx_unlock(&tiw_lock);
return;
}
@@ -278,7 +262,7 @@ static ERTS_INLINE void bump_timer_internal(long dt) /* PRE: tiw_lock is write-l
}
tiw_pos = keep_pos;
- tiw_write_unlock();
+ erts_smp_mtx_unlock(&tiw_lock);
/* Call timedout timers callbacks */
while (timeout_head) {
@@ -299,13 +283,13 @@ static ERTS_INLINE void bump_timer_internal(long dt) /* PRE: tiw_lock is write-l
#if defined(ERTS_TIMER_THREAD)
static void timer_thread_bump_timer(void)
{
- tiw_write_lock();
+ erts_smp_mtx_lock(&tiw_lock);
bump_timer_internal(do_time_reset());
}
#else
void bump_timer(long dt) /* dt is value from do_time */
{
- tiw_write_lock();
+ erts_smp_mtx_lock(&tiw_lock);
bump_timer_internal(dt);
}
#endif
@@ -324,7 +308,7 @@ static int timer_thread_setup_delay(SysTimeval *rem_time)
long elapsed;
int ticks;
- tiw_write_lock();
+ erts_smp_mtx_lock(&tiw_lock);
elapsed = do_time_update();
ticks = next_time_internal();
if (ticks == -1) /* timer queue empty */
@@ -336,7 +320,7 @@ static int timer_thread_setup_delay(SysTimeval *rem_time)
rem_time->tv_sec = ticks / 1000;
rem_time->tv_usec = 1000 * (ticks % 1000);
ticks_end = ticks;
- tiw_write_unlock();
+ erts_smp_mtx_unlock(&tiw_lock);
return ticks;
}
@@ -399,7 +383,7 @@ init_time(void)
if timer thread is enabled */
itime = erts_init_time_sup();
- tiw_init_lock();
+ erts_smp_mtx_init(&tiw_lock, "timer_wheel");
tiw = (ErlTimer**) erts_alloc(ERTS_ALC_T_TIMER_WHEEL,
TIW_SIZE * sizeof(ErlTimer*));
@@ -451,9 +435,9 @@ erl_set_timer(ErlTimer* p, ErlTimeoutProc timeout, ErlCancelProc cancel,
void* arg, Uint t)
{
erts_deliver_time();
- tiw_write_lock();
+ erts_smp_mtx_lock(&tiw_lock);
if (p->active) { /* XXX assert ? */
- tiw_write_unlock();
+ erts_smp_mtx_unlock(&tiw_lock);
return;
}
p->timeout = timeout;
@@ -461,7 +445,7 @@ erl_set_timer(ErlTimer* p, ErlTimeoutProc timeout, ErlCancelProc cancel,
p->arg = arg;
p->active = 1;
insert_timer(p, t);
- tiw_write_unlock();
+ erts_smp_mtx_unlock(&tiw_lock);
#if defined(ERTS_SMP) && !defined(ERTS_TIMER_THREAD)
if (t <= (Uint) LONG_MAX)
erts_sys_schedule_interrupt_timed(1, (long) t);
@@ -474,9 +458,9 @@ erl_cancel_timer(ErlTimer* p)
ErlTimer *tp;
ErlTimer **prev;
- tiw_write_lock();
+ erts_smp_mtx_lock(&tiw_lock);
if (!p->active) { /* allow repeated cancel (drivers) */
- tiw_write_unlock();
+ erts_smp_mtx_unlock(&tiw_lock);
return;
}
/* find p in linked list at slot p->slot and remove it */
@@ -489,17 +473,17 @@ erl_cancel_timer(ErlTimer* p)
p->slot = p->count = 0;
p->active = 0;
if (p->cancel != NULL) {
- tiw_write_unlock();
+ erts_smp_mtx_unlock(&tiw_lock);
(*p->cancel)(p->arg);
} else {
- tiw_write_unlock();
+ erts_smp_mtx_unlock(&tiw_lock);
}
return;
} else {
prev = &tp->next;
}
}
- tiw_write_unlock();
+ erts_smp_mtx_unlock(&tiw_lock);
}
/*
@@ -514,10 +498,10 @@ time_left(ErlTimer *p)
Uint left;
long dt;
- tiw_read_lock();
+ erts_smp_mtx_lock(&tiw_lock);
if (!p->active) {
- tiw_read_unlock();
+ erts_smp_mtx_unlock(&tiw_lock);
return 0;
}
@@ -531,7 +515,7 @@ time_left(ErlTimer *p)
else
left -= dt;
- tiw_read_unlock();
+ erts_smp_mtx_unlock(&tiw_lock);
return left * itime;
}
@@ -543,7 +527,7 @@ void p_slpq()
int i;
ErlTimer* p;
- tiw_read_lock();
+ erts_smp_mtx_lock(&tiw_lock);
/* print the whole wheel, starting at the current position */
erts_printf("\ntiw_pos = %d tiw_nto %d\n", tiw_pos, tiw_nto);
@@ -565,7 +549,7 @@ void p_slpq()
}
}
- tiw_read_unlock();
+ erts_smp_mtx_unlock(&tiw_lock);
}
#endif /* DEBUG */
diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c
index 25472ef47a..ab5e8b5d4a 100644
--- a/erts/emulator/beam/utils.c
+++ b/erts/emulator/beam/utils.c
@@ -48,11 +48,11 @@
#undef M_MMAP_THRESHOLD
#undef M_MMAP_MAX
-#if !defined(ELIB_ALLOC_IS_CLIB) && defined(__GLIBC__) && defined(HAVE_MALLOC_H)
+#if defined(__GLIBC__) && defined(HAVE_MALLOC_H)
#include <malloc.h>
#endif
-#if defined(ELIB_ALLOC_IS_CLIB) || !defined(HAVE_MALLOPT)
+#if !defined(HAVE_MALLOPT)
#undef HAVE_MALLOPT
#define HAVE_MALLOPT 0
#endif
diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c
index 60ae4cb108..c450f10f48 100644
--- a/erts/emulator/drivers/common/efile_drv.c
+++ b/erts/emulator/drivers/common/efile_drv.c
@@ -104,7 +104,7 @@
#include <ctype.h>
#include <sys/types.h>
-extern void erl_exit(int n, char *fmt, _DOTS_);
+void erl_exit(int n, char *fmt, ...);
static ErlDrvSysInfo sys_info;
diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c
index 0ea54930ba..f07e4793d2 100644
--- a/erts/emulator/drivers/common/inet_drv.c
+++ b/erts/emulator/drivers/common/inet_drv.c
@@ -48,6 +48,15 @@
#include <sys/uio.h>
#endif
+#ifdef HAVE_NET_IF_DL_H
+#include <net/if_dl.h>
+#endif
+#ifdef HAVE_IFADDRS_H
+#include <ifaddrs.h>
+#endif
+#ifdef HAVE_NETPACKET_PACKET_H
+#include <netpacket/packet.h>
+#endif
/* All platforms fail on malloc errors. */
#define FATAL_MALLOC
@@ -79,6 +88,7 @@
#include <winsock2.h>
#endif
#include <windows.h>
+#include <iphlpapi.h>
#include <Ws2tcpip.h> /* NEED VC 6.0 !!! */
@@ -461,6 +471,7 @@ static int my_strncasecmp(const char *s1, const char *s2, size_t n)
#define INET_REQ_IFGET 22
#define INET_REQ_IFSET 23
#define INET_REQ_SUBSCRIBE 24
+#define INET_REQ_GETIFADDRS 25
/* TCP requests */
#define TCP_REQ_ACCEPT 40
#define TCP_REQ_LISTEN 41
@@ -1045,7 +1056,7 @@ struct erl_drv_entry inet_driver_entry =
};
/* XXX: is this a driver interface function ??? */
-extern void erl_exit(int n, char*, _DOTS_);
+void erl_exit(int n, char*, ...);
/*
* Malloc wrapper,
@@ -2168,7 +2179,7 @@ static int http_error_inetdrv(void* arg, const char* buf, int len)
ErlDrvTermData spec[19];
if (desc->inet.active == INET_PASSIVE) {
- /* {inet_async,S,Ref,{error,{http_error,Line}}} */
+ /* {inet_async,S,Ref,{ok,{http_error,Line}}} */
int req;
int aid;
ErlDrvTermData caller;
@@ -2178,7 +2189,7 @@ static int http_error_inetdrv(void* arg, const char* buf, int len)
i = LOAD_ATOM(spec, i, am_inet_async);
i = LOAD_PORT(spec, i, desc->inet.dport);
i = LOAD_INT(spec, i, aid);
- i = LOAD_ATOM(spec, i, am_error);
+ i = LOAD_ATOM(spec, i, am_ok);
i = LOAD_ATOM(spec, i, am_http_error);
i = http_load_string(desc, spec, i, buf, len);
i = LOAD_TUPLE(spec, i, 2);
@@ -3818,39 +3829,81 @@ do { if ((end)-(ptr) < (n)) goto error; } while(0)
static char* sockaddr_to_buf(struct sockaddr* addr, char* ptr, char* end)
{
if (addr->sa_family == AF_INET || addr->sa_family == 0) {
- struct in_addr a;
- buf_check(ptr,end,sizeof(struct in_addr));
- a = ((struct sockaddr_in*) addr)->sin_addr;
- sys_memcpy(ptr, (char*)&a, sizeof(struct in_addr));
- return ptr + sizeof(struct in_addr);
+ struct in_addr *p = &(((struct sockaddr_in*) addr)->sin_addr);
+ buf_check(ptr, end, 1 + sizeof(struct in_addr));
+ *ptr = INET_AF_INET;
+ sys_memcpy(ptr+1, (char*)p, sizeof(struct in_addr));
+ return ptr + 1 + sizeof(struct in_addr);
}
#if defined(HAVE_IN6) && defined(AF_INET6)
else if (addr->sa_family == AF_INET6) {
- struct in6_addr a;
- buf_check(ptr,end,sizeof(struct in6_addr));
- a = ((struct sockaddr_in6*) addr)->sin6_addr;
- sys_memcpy(ptr, (char*)&a, sizeof(struct in6_addr));
- return ptr + sizeof(struct in6_addr);
+ struct in6_addr *p = &(((struct sockaddr_in6*) addr)->sin6_addr);
+ buf_check(ptr, end, 1 + sizeof(struct in6_addr));
+ *ptr = INET_AF_INET6;
+ sys_memcpy(ptr+1, (char*)p, sizeof(struct in6_addr));
+ return ptr + 1 + sizeof(struct in6_addr);
+ }
+#endif
+#if defined(AF_LINK)
+ else if (addr->sa_family == AF_LINK) {
+ struct sockaddr_dl *sdl_p = (struct sockaddr_dl*) addr;
+ buf_check(ptr, end, 2 + sdl_p->sdl_alen);
+ put_int16(sdl_p->sdl_alen, ptr); ptr += 2;
+ sys_memcpy(ptr, sdl_p->sdl_data + sdl_p->sdl_nlen, sdl_p->sdl_alen);
+ return ptr + sdl_p->sdl_alen;
}
#endif
+#if defined(AF_PACKET) && defined(HAVE_NETPACKET_PACKET_H)
+ else if(addr->sa_family == AF_PACKET) {
+ struct sockaddr_ll *sll_p = (struct sockaddr_ll*) addr;
+ buf_check(ptr, end, 2 + sll_p->sll_halen);
+ put_int16(sll_p->sll_halen, ptr); ptr += 2;
+ sys_memcpy(ptr, sll_p->sll_addr, sll_p->sll_halen);
+ return ptr + sll_p->sll_halen;
+ }
+#endif
+ return ptr;
error:
return NULL;
-
}
static char* buf_to_sockaddr(char* ptr, char* end, struct sockaddr* addr)
{
- buf_check(ptr,end,sizeof(struct in_addr));
- sys_memcpy((char*) &((struct sockaddr_in*)addr)->sin_addr, ptr,
- sizeof(struct in_addr));
- addr->sa_family = AF_INET;
- return ptr + sizeof(struct in_addr);
-
+ buf_check(ptr,end,1);
+ switch (*ptr++) {
+ case INET_AF_INET: {
+ struct in_addr *p = &((struct sockaddr_in*)addr)->sin_addr;
+ buf_check(ptr,end,sizeof(struct in_addr));
+ sys_memcpy((char*) p, ptr, sizeof(struct in_addr));
+ addr->sa_family = AF_INET;
+ return ptr + sizeof(struct in_addr);
+ }
+ case INET_AF_INET6: {
+ struct in6_addr *p = &((struct sockaddr_in6*)addr)->sin6_addr;
+ buf_check(ptr,end,sizeof(struct in6_addr));
+ sys_memcpy((char*) p, ptr, sizeof(struct in6_addr));
+ addr->sa_family = AF_INET6;
+ return ptr + sizeof(struct in6_addr);
+ }
+ }
error:
return NULL;
}
+#if defined (IFF_POINTOPOINT)
+#define IFGET_FLAGS(cflags) IFGET_FLAGS_P2P(cflags, IFF_POINTOPOINT)
+#elif defined IFF_POINTTOPOINT
+#define IFGET_FLAGS(cflags) IFGET_FLAGS_P2P(cflags, IFF_POINTTOPOINT)
+#endif
+
+#define IFGET_FLAGS_P2P(cflags, iff_ptp) \
+ ((((cflags) & IFF_UP) ? INET_IFF_UP : 0) | \
+ (((cflags) & IFF_BROADCAST) ? INET_IFF_BROADCAST : 0) | \
+ (((cflags) & IFF_LOOPBACK) ? INET_IFF_LOOPBACK : 0) | \
+ (((cflags) & iff_ptp) ? INET_IFF_POINTTOPOINT : 0) | \
+ (((cflags) & IFF_UP) ? INET_IFF_RUNNING : 0) | /* emulate running ? */ \
+ (((cflags) & IFF_MULTICAST) ? INET_IFF_MULTICAST : 0))
#if defined(__WIN32__) && defined(SIO_GET_INTERFACE_LIST)
@@ -3888,7 +3941,6 @@ static int inet_ctl_getiflist(inet_descriptor* desc, char** rbuf, int rsize)
return ctl_reply(INET_REP_OK, sbuf, sptr - sbuf, rbuf, rsize);
}
-
/* input is an ip-address in string format i.e A.B.C.D
** scan the INTERFACE_LIST to get the options
*/
@@ -3905,7 +3957,7 @@ static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len,
INTERFACE_INFO* ifp;
long namaddr;
- if ((len == 0) || ((namlen = buf[0]) > len))
+ if ((len == 0) || ((namlen = get_int8(buf)) > len))
goto error;
if (parse_addr(buf+1, namlen, &namaddr) < 0)
goto error;
@@ -3974,27 +4026,12 @@ static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len,
break;
case INET_IFOPT_FLAGS: {
- long eflags = 0;
int flags = ifp->iiFlags;
/* just enumerate the interfaces (no names) */
- /* translate flags */
- if (flags & IFF_UP)
- eflags |= INET_IFF_UP;
- if (flags & IFF_BROADCAST)
- eflags |= INET_IFF_BROADCAST;
- if (flags & IFF_LOOPBACK)
- eflags |= INET_IFF_LOOPBACK;
- if (flags & IFF_POINTTOPOINT)
- eflags |= INET_IFF_POINTTOPOINT;
- if (flags & IFF_UP) /* emulate runnign ? */
- eflags |= INET_IFF_RUNNING;
- if (flags & IFF_MULTICAST)
- eflags |= INET_IFF_MULTICAST;
-
buf_check(sptr, s_end, 5);
*sptr++ = INET_IFOPT_FLAGS;
- put_int32(eflags, sptr);
+ put_int32(IFGET_FLAGS(flags), sptr);
sptr += 4;
break;
}
@@ -4015,7 +4052,6 @@ static int inet_ctl_ifset(inet_descriptor* desc, char* buf, int len,
return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize);
}
-
#elif defined(SIOCGIFCONF) && defined(SIOCSIFFLAGS)
/* cygwin has SIOCGIFCONF but not SIOCSIFFLAGS (Nov 2002) */
@@ -4026,69 +4062,81 @@ static int inet_ctl_ifset(inet_descriptor* desc, char* buf, int len,
#define SIZEA(p) (sizeof (p))
#endif
-
-static int inet_ctl_getiflist(inet_descriptor* desc, char** rbuf, int rsize)
-{
- struct ifconf ifc;
- struct ifreq *ifr;
- char *buf;
- int buflen, ifc_len, i;
- char *sbuf, *sp;
-
- /* Courtesy of Per Bergqvist and W. Richard Stevens */
-
- ifc_len = 0;
- buflen = 100 * sizeof(struct ifreq);
- buf = ALLOC(buflen);
+static int get_ifconf(SOCKET s, struct ifconf *ifcp) {
+ int ifc_len = 0;
+ int buflen = 100 * sizeof(struct ifreq);
+ char *buf = ALLOC(buflen);
for (;;) {
- ifc.ifc_len = buflen;
- ifc.ifc_buf = buf;
- if (ioctl(desc->s, SIOCGIFCONF, (char *)&ifc) < 0) {
+ ifcp->ifc_len = buflen;
+ ifcp->ifc_buf = buf;
+ if (ioctl(s, SIOCGIFCONF, (char *)ifcp) < 0) {
int res = sock_errno();
if (res != EINVAL || ifc_len) {
FREE(buf);
- return ctl_error(res, rbuf, rsize);
+ return -1;
}
} else {
- if (ifc.ifc_len == ifc_len) break; /* buf large enough */
- ifc_len = ifc.ifc_len;
+ if (ifcp->ifc_len == ifc_len) break; /* buf large enough */
+ ifc_len = ifcp->ifc_len;
}
buflen += 10 * sizeof(struct ifreq);
buf = (char *)REALLOC(buf, buflen);
}
-
- sp = sbuf = ALLOC(ifc_len+1);
+ return 0;
+}
+
+static void free_ifconf(struct ifconf *ifcp) {
+ FREE(ifcp->ifc_buf);
+}
+
+static int inet_ctl_getiflist(inet_descriptor* desc, char** rbuf, int rsize)
+{
+ struct ifconf ifc;
+ struct ifreq *ifrp;
+ char *sbuf, *sp;
+ int i;
+
+ /* Courtesy of Per Bergqvist and W. Richard Stevens */
+
+ if (get_ifconf(desc->s, &ifc) < 0) {
+ return ctl_error(sock_errno(), rbuf, rsize);
+ }
+
+ sp = sbuf = ALLOC(ifc.ifc_len+1);
*sp++ = INET_REP_OK;
i = 0;
for (;;) {
int n;
-
- ifr = (struct ifreq *) VOIDP(buf + i);
- n = sizeof(ifr->ifr_name) + SIZEA(ifr->ifr_addr);
- if (n < sizeof(*ifr)) n = sizeof(*ifr);
- if (i+n > ifc_len) break;
+
+ ifrp = (struct ifreq *) VOIDP(ifc.ifc_buf + i);
+ n = sizeof(ifrp->ifr_name) + SIZEA(ifrp->ifr_addr);
+ if (n < sizeof(*ifrp)) n = sizeof(*ifrp);
+ if (i+n > ifc.ifc_len) break;
i += n;
-
- switch (ifr->ifr_addr.sa_family) {
+
+ switch (ifrp->ifr_addr.sa_family) {
#if defined(HAVE_IN6) && defined(AF_INET6)
case AF_INET6:
#endif
case AF_INET:
- ASSERT(sp+IFNAMSIZ+1 < sbuf+buflen+1)
- strncpy(sp, ifr->ifr_name, IFNAMSIZ);
+ ASSERT(sp+IFNAMSIZ+1 < sbuf+ifc.ifc_len+1)
+ strncpy(sp, ifrp->ifr_name, IFNAMSIZ);
sp[IFNAMSIZ] = '\0';
sp += strlen(sp), ++sp;
}
-
- if (i >= ifc_len) break;
+
+ if (i >= ifc.ifc_len) break;
}
- FREE(buf);
+ free_ifconf(&ifc);
*rbuf = sbuf;
return sp - sbuf;
}
-
+/* FIXME: temporary hack */
+#ifndef IFHWADDRLEN
+#define IFHWADDRLEN 6
+#endif
static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len,
char** rbuf, int rsize)
@@ -4099,11 +4147,11 @@ static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len,
struct ifreq ifreq;
int namlen;
- if ((len == 0) || ((namlen = buf[0]) > len))
+ if ((len == 0) || ((namlen = get_int8(buf)) > len))
goto error;
sys_memset(ifreq.ifr_name, '\0', IFNAMSIZ);
sys_memcpy(ifreq.ifr_name, buf+1,
- (namlen > IFNAMSIZ) ? IFNAMSIZ : namlen);
+ (namlen >= IFNAMSIZ) ? IFNAMSIZ-1 : namlen);
buf += (namlen+1);
len -= (namlen+1);
sptr = sbuf;
@@ -4123,11 +4171,52 @@ static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len,
#ifdef SIOCGIFHWADDR
if (ioctl(desc->s, SIOCGIFHWADDR, (char *)&ifreq) < 0)
break;
- buf_check(sptr, s_end, 1+IFHWADDRLEN);
+ buf_check(sptr, s_end, 1+2+IFHWADDRLEN);
*sptr++ = INET_IFOPT_HWADDR;
+ put_int16(IFHWADDRLEN, sptr); sptr += 2;
/* raw memcpy (fix include autoconf later) */
sys_memcpy(sptr, (char*)(&ifreq.ifr_hwaddr.sa_data), IFHWADDRLEN);
sptr += IFHWADDRLEN;
+#elif defined(SIOCGENADDR)
+ if (ioctl(desc->s, SIOCGENADDR, (char *)&ifreq) < 0)
+ break;
+ buf_check(sptr, s_end, 1+2+sizeof(ifreq.ifr_enaddr));
+ *sptr++ = INET_IFOPT_HWADDR;
+ put_int16(sizeof(ifreq.ifr_enaddr), sptr); sptr += 2;
+ /* raw memcpy (fix include autoconf later) */
+ sys_memcpy(sptr, (char*)(&ifreq.ifr_enaddr),
+ sizeof(ifreq.ifr_enaddr));
+ sptr += sizeof(ifreq.ifr_enaddr);
+#elif defined(HAVE_GETIFADDRS) && defined(AF_LINK)
+ struct ifaddrs *ifa, *ifp;
+ struct sockaddr_dl *sdlp;
+ int found = 0;
+
+ if (getifaddrs(&ifa) == -1)
+ goto error;
+
+ for (ifp = ifa; ifp; ifp = ifp->ifa_next) {
+ if ((ifp->ifa_addr->sa_family == AF_LINK) &&
+ (sys_strcmp(ifp->ifa_name, ifreq.ifr_name) == 0)) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (found == 0) {
+ freeifaddrs(ifa);
+ break;
+ }
+ sdlp = (struct sockaddr_dl *)ifp->ifa_addr;
+
+ buf_check(sptr, s_end, 1+2+sdlp->sdl_alen);
+ *sptr++ = INET_IFOPT_HWADDR;
+ put_int16(sdlp->sdl_alen, sptr); sptr += 2;
+ sys_memcpy(sptr,
+ sdlp->sdl_data + sdlp->sdl_nlen,
+ sdlp->sdl_alen);
+ freeifaddrs(ifa);
+ sptr += sdlp->sdl_alen;
#endif
break;
}
@@ -4204,29 +4293,15 @@ static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len,
case INET_IFOPT_FLAGS: {
int flags;
- int eflags = 0;
if (ioctl(desc->s, SIOCGIFFLAGS, (char*)&ifreq) < 0)
flags = 0;
else
flags = ifreq.ifr_flags;
- /* translate flags */
- if (flags & IFF_UP)
- eflags |= INET_IFF_UP;
- if (flags & IFF_BROADCAST)
- eflags |= INET_IFF_BROADCAST;
- if (flags & IFF_LOOPBACK)
- eflags |= INET_IFF_LOOPBACK;
- if (flags & IFF_POINTOPOINT)
- eflags |= INET_IFF_POINTTOPOINT;
- if (flags & IFF_RUNNING)
- eflags |= INET_IFF_RUNNING;
- if (flags & IFF_MULTICAST)
- eflags |= INET_IFF_MULTICAST;
buf_check(sptr, s_end, 5);
*sptr++ = INET_IFOPT_FLAGS;
- put_int32(eflags, sptr);
+ put_int32(IFGET_FLAGS(flags), sptr);
sptr += 4;
break;
}
@@ -4240,10 +4315,6 @@ static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len,
return ctl_error(EINVAL, rbuf, rsize);
}
-/* FIXME: temporary hack */
-#ifndef IFHWADDRLEN
-#define IFHWADDRLEN 6
-#endif
static int inet_ctl_ifset(inet_descriptor* desc, char* buf, int len,
char** rbuf, int rsize)
@@ -4252,11 +4323,11 @@ static int inet_ctl_ifset(inet_descriptor* desc, char* buf, int len,
int namlen;
char* b_end = buf + len;
- if ((len == 0) || ((namlen = buf[0]) > len))
+ if ((len == 0) || ((namlen = get_int8(buf)) > len))
goto error;
sys_memset(ifreq.ifr_name, '\0', IFNAMSIZ);
sys_memcpy(ifreq.ifr_name, buf+1,
- (namlen > IFNAMSIZ) ? IFNAMSIZ : namlen);
+ (namlen >= IFNAMSIZ) ? IFNAMSIZ-1 : namlen);
buf += (namlen+1);
len -= (namlen+1);
@@ -4268,17 +4339,22 @@ static int inet_ctl_ifset(inet_descriptor* desc, char* buf, int len,
(void) ioctl(desc->s, SIOCSIFADDR, (char*)&ifreq);
break;
- case INET_IFOPT_HWADDR:
- buf_check(buf, b_end, IFHWADDRLEN);
+ case INET_IFOPT_HWADDR: {
+ unsigned int len;
+ buf_check(buf, b_end, 2);
+ len = get_int16(buf); buf += 2;
+ buf_check(buf, b_end, len);
#ifdef SIOCSIFHWADDR
/* raw memcpy (fix include autoconf later) */
- sys_memcpy((char*)(&ifreq.ifr_hwaddr.sa_data), buf, IFHWADDRLEN);
+ sys_memset((char*)(&ifreq.ifr_hwaddr.sa_data),
+ '\0', sizeof(ifreq.ifr_hwaddr.sa_data));
+ sys_memcpy((char*)(&ifreq.ifr_hwaddr.sa_data), buf, len);
(void) ioctl(desc->s, SIOCSIFHWADDR, (char *)&ifreq);
#endif
- buf += IFHWADDRLEN;
+ buf += len;
break;
-
+ }
case INET_IFOPT_BROADADDR:
#ifdef SIOCSIFBRDADDR
@@ -4383,6 +4459,551 @@ static int inet_ctl_ifset(inet_descriptor* desc, char* buf, int len,
#endif
+
+
+/* Latin-1 to utf8 */
+
+static int utf8_len(const char *c, int m) {
+ int l;
+ for (l = 0; m; c++, l++, m--) {
+ if (*c == '\0') break;
+ if ((*c & 0x7f) != *c) l++;
+ }
+ return l;
+}
+
+static void utf8_encode(const char *c, int m, char *p) {
+ for (; m; c++, m--) {
+ if (*c == '\0') break;
+ if ((*c & 0x7f) != *c) {
+ *p++ = (char) (0xC0 | (0x03 & (*c >> 6)));
+ *p++ = (char) (0x80 | (0x3F & *c));
+ } else {
+ *p++ = (char) *c;
+ }
+ }
+}
+
+#if defined(__WIN32__)
+
+static void set_netmask_bytes(char *c, int len, int pref_len) {
+ int i, m;
+ for (i = 0, m = pref_len >> 3; i < m && i < len; i++) c[i] = '\xFF';
+ if (i < len) c[i++] = 0xFF << (8 - (pref_len & 7));
+ for (; i < len; i++) c[i] = '\0';
+}
+
+
+int eq_masked_bytes(char *a, char *b, int pref_len) {
+ int i, m;
+ for (i = 0, m = pref_len >> 3; i < m; i++) {
+ if (a[i] != b[i]) return 0;
+ }
+ m = pref_len & 7;
+ if (m) {
+ m = 0xFF & (0xFF << (8 - m));
+ if ((a[i] & m) != (b[i] & m)) return 0;
+ }
+ return !0;
+}
+
+static int inet_ctl_getifaddrs(inet_descriptor* desc_p,
+ char **rbuf_pp, int rsize)
+{
+ int i;
+ DWORD ret, n;
+ IP_INTERFACE_INFO *info_p;
+ MIB_IPADDRTABLE *ip_addrs_p;
+ IP_ADAPTER_ADDRESSES *ip_adaddrs_p, *ia_p;
+
+ char *buf_p;
+ char *buf_alloc_p;
+ int buf_size =512;
+# define BUF_ENSURE(Size) \
+ do { \
+ int NEED_, GOT_ = buf_p - buf_alloc_p; \
+ NEED_ = GOT_ + (Size); \
+ if (NEED_ > buf_size) { \
+ buf_size = NEED_ + 512; \
+ buf_alloc_p = REALLOC(buf_alloc_p, buf_size); \
+ buf_p = buf_alloc_p + GOT_; \
+ } \
+ } while(0)
+# define SOCKADDR_TO_BUF(opt, sa) \
+ do { \
+ if (sa) { \
+ char *P_; \
+ *buf_p++ = (opt); \
+ while (! (P_ = sockaddr_to_buf((sa), buf_p, \
+ buf_alloc_p+buf_size))) { \
+ int GOT_ = buf_p - buf_alloc_p; \
+ buf_size += 512; \
+ buf_alloc_p = REALLOC(buf_alloc_p, buf_size); \
+ buf_p = buf_alloc_p + GOT_; \
+ } \
+ if (P_ == buf_p) { \
+ buf_p--; \
+ } else { \
+ buf_p = P_; \
+ } \
+ } \
+ } while (0)
+
+ {
+ /* Try GetAdaptersAddresses, if it is available */
+ unsigned long ip_adaddrs_size = 16 * 1024;
+ ULONG family = AF_UNSPEC;
+ ULONG flags =
+ GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST |
+ GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME |
+ GAA_FLAG_SKIP_MULTICAST;
+ ULONG (WINAPI *fpGetAdaptersAddresses)
+ (ULONG, ULONG, PVOID, PIP_ADAPTER_ADDRESSES, PULONG);
+ HMODULE iphlpapi = GetModuleHandle("iphlpapi");
+ fpGetAdaptersAddresses = (void *)
+ (iphlpapi ?
+ GetProcAddress(iphlpapi, "GetAdaptersAddresses") :
+ NULL);
+ if (fpGetAdaptersAddresses) {
+ ip_adaddrs_p = ALLOC(ip_adaddrs_size);
+ for (i = 17; i; i--) {
+ ret = fpGetAdaptersAddresses(
+ family, flags, NULL, ip_adaddrs_p, &ip_adaddrs_size);
+ ip_adaddrs_p = REALLOC(ip_adaddrs_p, ip_adaddrs_size);
+ if (ret == NO_ERROR) break;
+ if (ret == ERROR_BUFFER_OVERFLOW) continue;
+ i = 0;
+ }
+ if (! i) {
+ FREE(ip_adaddrs_p);
+ ip_adaddrs_p = NULL;
+ }
+ } else ip_adaddrs_p = NULL;
+ }
+
+ {
+ /* Load the IP_INTERFACE_INFO table (only IPv4 interfaces),
+ * reliable source of interface names on XP
+ */
+ unsigned long info_size = 4 * 1024;
+ info_p = ALLOC(info_size);
+ for (i = 17; i; i--) {
+ ret = GetInterfaceInfo(info_p, &info_size);
+ info_p = REALLOC(info_p, info_size);
+ if (ret == NO_ERROR) break;
+ if (ret == ERROR_INSUFFICIENT_BUFFER) continue;
+ i = 0;
+ }
+ if (! i) {
+ FREE(info_p);
+ info_p = NULL;
+ }
+ }
+
+ if (! ip_adaddrs_p) {
+ /* If GetAdaptersAddresses gave nothing we fall back to
+ * MIB_IPADDRTABLE (only IPv4 interfaces)
+ */
+ unsigned long ip_addrs_size = 16 * sizeof(*ip_addrs_p);
+ ip_addrs_p = ALLOC(ip_addrs_size);
+ for (i = 17; i; i--) {
+ ret = GetIpAddrTable(ip_addrs_p, &ip_addrs_size, FALSE);
+ ip_addrs_p = REALLOC(ip_addrs_p, ip_addrs_size);
+ if (ret == NO_ERROR) break;
+ if (ret == ERROR_INSUFFICIENT_BUFFER) continue;
+ i = 0;
+ }
+ if (! i) {
+ if (info_p) FREE(info_p);
+ FREE(ip_addrs_p);
+ return ctl_reply(INET_REP_OK, NULL, 0, rbuf_pp, rsize);
+ }
+ } else ip_addrs_p = NULL;
+
+ buf_p = buf_alloc_p = ALLOC(buf_size);
+ *buf_p++ = INET_REP_OK;
+
+ /* Iterate over MIB_IPADDRTABLE or IP_ADAPTER_ADDRESSES */
+ for (ia_p = NULL, ip_addrs_p ? ((void *)(i = 0)) : (ia_p = ip_adaddrs_p);
+ ip_addrs_p ? (i < ip_addrs_p->dwNumEntries) : (ia_p != NULL);
+ ip_addrs_p ? ((void *)(i++)) : (ia_p = ia_p->Next)) {
+ MIB_IPADDRROW *ipaddrrow_p = NULL;
+ DWORD flags = INET_IFF_MULTICAST;
+ DWORD index = 0;
+ WCHAR *wname_p = NULL;
+ MIB_IFROW ifrow;
+
+ if (ip_addrs_p) {
+ ipaddrrow_p = ip_addrs_p->table + i;
+ index = ipaddrrow_p->dwIndex;
+ } else {
+ index = ia_p->IfIndex;
+ if (ia_p->Flags & IP_ADAPTER_NO_MULTICAST) {
+ flags &= ~INET_IFF_MULTICAST;
+ }
+ }
+index:
+ if (! index) goto done;
+ sys_memzero(&ifrow, sizeof(ifrow));
+ ifrow.dwIndex = index;
+ if (GetIfEntry(&ifrow) != NO_ERROR) break;
+ /* Find the interface name - first try MIB_IFROW.wzname */
+ if (ifrow.wszName[0] != 0) {
+ wname_p = ifrow.wszName;
+ } else {
+ /* Then try IP_ADAPTER_INDEX_MAP.Name (only IPv4 adapters) */
+ int j;
+ for (j = 0; j < info_p->NumAdapters; j++) {
+ if (info_p->Adapter[j].Index == (ULONG) ifrow.dwIndex) {
+ if (info_p->Adapter[j].Name[0] != 0) {
+ wname_p = info_p->Adapter[j].Name;
+ }
+ break;
+ }
+ }
+ }
+ if (wname_p) {
+ int len;
+ /* Convert interface name to UTF-8 */
+ len =
+ WideCharToMultiByte(
+ CP_UTF8, 0, wname_p, -1, NULL, 0, NULL, NULL);
+ if (! len) break;
+ BUF_ENSURE(len);
+ WideCharToMultiByte(
+ CP_UTF8, 0, wname_p, -1, buf_p, len, NULL, NULL);
+ buf_p += len;
+ } else {
+ /* Found no name -
+ * use "MIB_IFROW.dwIndex: MIB_IFROW.bDescr" as name instead */
+ int l;
+ l = utf8_len(ifrow.bDescr, ifrow.dwDescrLen);
+ BUF_ENSURE(9 + l+1);
+ buf_p +=
+ erts_sprintf(
+ buf_p, "%lu: ", (unsigned long) ifrow.dwIndex);
+ utf8_encode(ifrow.bDescr, ifrow.dwDescrLen, buf_p);
+ buf_p += l;
+ *buf_p++ = '\0';
+ }
+ /* Interface flags, often make up broadcast and multicast flags */
+ switch (ifrow.dwType) {
+ case IF_TYPE_ETHERNET_CSMACD:
+ flags |= INET_IFF_BROADCAST;
+ break;
+ case IF_TYPE_SOFTWARE_LOOPBACK:
+ flags |= INET_IFF_LOOPBACK;
+ flags &= ~INET_IFF_MULTICAST;
+ break;
+ default:
+ flags &= ~INET_IFF_MULTICAST;
+ break;
+ }
+ if (ifrow.dwAdminStatus) {
+ flags |= INET_IFF_UP;
+ switch (ifrow.dwOperStatus) {
+ case IF_OPER_STATUS_CONNECTING:
+ flags |= INET_IFF_POINTTOPOINT;
+ break;
+ case IF_OPER_STATUS_CONNECTED:
+ flags |= INET_IFF_RUNNING | INET_IFF_POINTTOPOINT;
+ break;
+ case IF_OPER_STATUS_OPERATIONAL:
+ flags |= INET_IFF_RUNNING;
+ break;
+ }
+ }
+ BUF_ENSURE(1 + 4);
+ *buf_p++ = INET_IFOPT_FLAGS;
+ put_int32(flags, buf_p); buf_p += 4;
+ if (ipaddrrow_p) {
+ /* Legacy implementation through GetIpAddrTable */
+ struct sockaddr_in sin;
+ /* IP Address */
+ sys_memzero(&sin, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = ipaddrrow_p->dwAddr;
+ BUF_ENSURE(1);
+ /* Netmask */
+ SOCKADDR_TO_BUF(INET_IFOPT_ADDR, (struct sockaddr *) &sin);
+ sin.sin_addr.s_addr = ipaddrrow_p->dwMask;
+ BUF_ENSURE(1);
+ SOCKADDR_TO_BUF(INET_IFOPT_NETMASK, (struct sockaddr *) &sin);
+ if (flags & INET_IFF_BROADCAST) {
+ /* Broadcast address - fake it*/
+ sin.sin_addr.s_addr = ipaddrrow_p->dwAddr;
+ sin.sin_addr.s_addr |= ~ipaddrrow_p->dwMask;
+ BUF_ENSURE(1);
+ SOCKADDR_TO_BUF(
+ INET_IFOPT_BROADADDR, (struct sockaddr *) &sin);
+ }
+ } else {
+ IP_ADAPTER_UNICAST_ADDRESS *p;
+ /* IP Address(es) */
+ for (p = ia_p->FirstUnicastAddress;
+ p;
+ p = p->Next)
+ {
+ IP_ADAPTER_PREFIX *q;
+ ULONG shortest_length;
+ struct sockaddr *shortest_p, *sa_p = p->Address.lpSockaddr;
+ BUF_ENSURE(1);
+ SOCKADDR_TO_BUF(INET_IFOPT_ADDR, sa_p);
+ shortest_p = NULL;
+ shortest_length = 0;
+ for (q = ia_p->FirstPrefix;
+ q;
+ q = q->Next) {
+ struct sockaddr *sp_p = q->Address.lpSockaddr;
+ if (sa_p->sa_family != sp_p->sa_family) continue;
+ switch (sa_p->sa_family) {
+ case AF_INET: {
+ struct sockaddr_in sin;
+ DWORD sa, sp, mask;
+ sa = ntohl((DWORD)
+ ((struct sockaddr_in *)
+ sa_p)->sin_addr.s_addr);
+ sp = ntohl((DWORD)
+ ((struct sockaddr_in *)
+ sp_p)->sin_addr.s_addr);
+ mask = 0xFFFFFFFF << (32 - q->PrefixLength);
+ if ((sa & mask) != (sp & mask)) continue;
+ if ((! shortest_p)
+ || q->PrefixLength < shortest_length) {
+ shortest_p = sp_p;
+ shortest_length = q->PrefixLength;
+ }
+ } break;
+ case AF_INET6: {
+ struct sockaddr_in6 sin6;
+ if (!eq_masked_bytes((char *)
+ &((struct sockaddr_in6 *)
+ sa_p)->sin6_addr,
+ (char *)
+ &((struct sockaddr_in6 *)
+ sp_p)->sin6_addr,
+ q->PrefixLength)) {
+ continue;
+ }
+ if ((! shortest_p)
+ || q->PrefixLength < shortest_length) {
+ shortest_p = sp_p;
+ shortest_length = q->PrefixLength;
+ }
+ } break;
+ }
+ }
+ if (! shortest_p) {
+ /* Found no shortest prefix */
+ shortest_p = sa_p;
+ switch (shortest_p->sa_family) {
+ case AF_INET: {
+ /* Fall back to old classfull network addresses */
+ DWORD addr = ntohl(((struct sockaddr_in *)shortest_p)
+ ->sin_addr.s_addr);
+ if (! (addr & 0x800000)) {
+ /* Class A */
+ shortest_length = 8;
+ } else if (! (addr & 0x400000)) {
+ /* Class B */
+ shortest_length = 16;
+ } else if (! (addr & 0x200000)) {
+ /* Class C */
+ shortest_length = 24;
+ } else {
+ shortest_length = 32;
+ }
+ } break;
+ case AF_INET6: {
+ /* Just play it safe */
+ shortest_length = 128;
+ } break;
+ }
+ }
+ switch (shortest_p->sa_family) {
+ case AF_INET: {
+ struct sockaddr_in sin;
+ DWORD mask = 0xFFFFFFFF << (32 - shortest_length);
+ sys_memzero(&sin, sizeof(sin));
+ sin.sin_family = shortest_p->sa_family;
+ sin.sin_addr.s_addr = htonl(mask);
+ BUF_ENSURE(1);
+ SOCKADDR_TO_BUF(INET_IFOPT_NETMASK,
+ (struct sockaddr *) &sin);
+ if (flags & INET_IFF_BROADCAST) {
+ DWORD sp =
+ ntohl((DWORD)
+ ((struct sockaddr_in *)shortest_p)
+ -> sin_addr.s_addr);
+ sin.sin_addr.s_addr = htonl(sp | ~mask);
+ BUF_ENSURE(1);
+ SOCKADDR_TO_BUF(INET_IFOPT_BROADADDR,
+ (struct sockaddr *) &sin);
+ }
+ } break;
+ case AF_INET6: {
+ struct sockaddr_in6 sin6;
+ sys_memzero(&sin6, sizeof(sin6));
+ sin6.sin6_family = shortest_p->sa_family;
+ set_netmask_bytes((char *) &sin6.sin6_addr,
+ 16,
+ shortest_length);
+ BUF_ENSURE(1);
+ SOCKADDR_TO_BUF(INET_IFOPT_NETMASK,
+ (struct sockaddr *) &sin6);
+ } break;
+ }
+ }
+ }
+ if (ifrow.dwPhysAddrLen) {
+ /* Hardware Address */
+ BUF_ENSURE(1 + 2 + ifrow.dwPhysAddrLen);
+ *buf_p++ = INET_IFOPT_HWADDR;
+ put_int16(ifrow.dwPhysAddrLen, buf_p); buf_p += 2;
+ sys_memcpy(buf_p, ifrow.bPhysAddr, ifrow.dwPhysAddrLen);
+ buf_p += ifrow.dwPhysAddrLen;
+ }
+
+done:
+ /* That is all for this interface */
+ BUF_ENSURE(1);
+ *buf_p++ = '\0';
+ if (ia_p &&
+ ia_p->Ipv6IfIndex &&
+ ia_p->Ipv6IfIndex != index)
+ {
+ /* Oops, there was an other interface for IPv6. Possible? XXX */
+ index = ia_p->Ipv6IfIndex;
+ goto index;
+ }
+ }
+
+ if (ip_adaddrs_p) FREE(ip_adaddrs_p);
+ if (info_p) FREE(info_p);
+ if (ip_addrs_p) FREE(ip_addrs_p);
+
+ buf_size = buf_p - buf_alloc_p;
+ buf_alloc_p = REALLOC(buf_alloc_p, buf_size);
+ /* buf_p is now unreliable */
+ *rbuf_pp = buf_alloc_p;
+ return buf_size;
+# undef BUF_ENSURE
+}
+
+#elif defined(HAVE_GETIFADDRS)
+
+static int inet_ctl_getifaddrs(inet_descriptor* desc_p,
+ char **rbuf_pp, int rsize)
+{
+ struct ifaddrs *ifa_p, *ifa_free_p;
+
+ int buf_size;
+ char *buf_p;
+ char *buf_alloc_p;
+
+ buf_size = 512;
+ buf_alloc_p = ALLOC(buf_size);
+ buf_p = buf_alloc_p;
+# define BUF_ENSURE(Size) \
+ do { \
+ int NEED_, GOT_ = buf_p - buf_alloc_p; \
+ NEED_ = GOT_ + (Size); \
+ if (NEED_ > buf_size) { \
+ buf_size = NEED_ + 512; \
+ buf_alloc_p = REALLOC(buf_alloc_p, buf_size); \
+ buf_p = buf_alloc_p + GOT_; \
+ } \
+ } while (0)
+# define SOCKADDR_TO_BUF(opt, sa) \
+ do { \
+ if (sa) { \
+ char *P_; \
+ *buf_p++ = (opt); \
+ while (! (P_ = sockaddr_to_buf((sa), buf_p, \
+ buf_alloc_p+buf_size))) { \
+ int GOT_ = buf_p - buf_alloc_p; \
+ buf_size += 512; \
+ buf_alloc_p = REALLOC(buf_alloc_p, buf_size); \
+ buf_p = buf_alloc_p + GOT_; \
+ } \
+ if (P_ == buf_p) { \
+ buf_p--; \
+ } else { \
+ buf_p = P_; \
+ } \
+ } \
+ } while (0)
+
+ if (getifaddrs(&ifa_p) < 0) {
+ return ctl_error(sock_errno(), rbuf_pp, rsize);
+ }
+ ifa_free_p = ifa_p;
+ *buf_p++ = INET_REP_OK;
+ for (; ifa_p; ifa_p = ifa_p->ifa_next) {
+ int len = utf8_len(ifa_p->ifa_name, -1);
+ BUF_ENSURE(len+1 + 1+4 + 1);
+ utf8_encode(ifa_p->ifa_name, -1, buf_p);
+ buf_p += len;
+ *buf_p++ = '\0';
+ *buf_p++ = INET_IFOPT_FLAGS;
+ put_int32(IFGET_FLAGS(ifa_p->ifa_flags), buf_p); buf_p += 4;
+ if (ifa_p->ifa_addr->sa_family == AF_INET
+#if defined(AF_INET6)
+ || ifa_p->ifa_addr->sa_family == AF_INET6
+#endif
+ ) {
+ SOCKADDR_TO_BUF(INET_IFOPT_ADDR, ifa_p->ifa_addr);
+ BUF_ENSURE(1);
+ SOCKADDR_TO_BUF(INET_IFOPT_NETMASK, ifa_p->ifa_netmask);
+ if (ifa_p->ifa_flags & IFF_POINTOPOINT) {
+ BUF_ENSURE(1);
+ SOCKADDR_TO_BUF(INET_IFOPT_DSTADDR, ifa_p->ifa_dstaddr);
+ } else if (ifa_p->ifa_flags & IFF_BROADCAST) {
+ BUF_ENSURE(1);
+ SOCKADDR_TO_BUF(INET_IFOPT_BROADADDR, ifa_p->ifa_broadaddr);
+ }
+ }
+#if defined(AF_LINK) || defined(AF_PACKET)
+ else if (
+#if defined(AF_LINK)
+ ifa_p->ifa_addr->sa_family == AF_LINK
+#else
+ 0
+#endif
+#if defined(AF_PACKET)
+ || ifa_p->ifa_addr->sa_family == AF_PACKET
+#endif
+ ) {
+ char *bp = buf_p;
+ BUF_ENSURE(1);
+ SOCKADDR_TO_BUF(INET_IFOPT_HWADDR, ifa_p->ifa_addr);
+ if (buf_p - bp < 4) buf_p = bp; /* Empty hwaddr */
+ }
+#endif
+ BUF_ENSURE(1);
+ *buf_p++ = '\0';
+ }
+ buf_size = buf_p - buf_alloc_p;
+ buf_alloc_p = REALLOC(buf_alloc_p, buf_size);
+ /* buf_p is now unreliable */
+ freeifaddrs(ifa_free_p);
+ *rbuf_pp = buf_alloc_p;
+ return buf_size;
+# undef BUF_ENSURE
+}
+
+#else
+
+static int inet_ctl_getifaddrs(inet_descriptor* desc_p,
+ char **rbuf_pp, int rsize)
+{
+ return ctl_error(ENOTSUP, rbuf_pp, rsize);
+}
+
+#endif
+
+
+
#ifdef VXWORKS
/*
** THIS is a terrible creature, a bug in the TCP part
@@ -5032,8 +5653,8 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
}
case INET_OPT_LINGER:
{
- CHKLEN(curr, ASSOC_ID_LEN + 2 + 4);
- arg.lin.l_onoff = get_int16 (curr); curr += 2;
+ CHKLEN(curr, 2*4);
+ arg.lin.l_onoff = get_int32 (curr); curr += 4;
arg.lin.l_linger = get_int32 (curr); curr += 4;
proto = SOL_SOCKET;
@@ -5261,12 +5882,15 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
if (pmtud_enable) cflags |= SPP_PMTUD_ENABLE;
if (pmtud_disable) cflags |= SPP_PMTUD_DISABLE;
+# ifdef HAVE_STRUCT_SCTP_PADDRPARAMS_SPP_SACKDELAY
+ /* The followings are missing in FreeBSD 7.1 */
sackdelay_enable =eflags& SCTP_FLAG_SACDELAY_ENABLE;
sackdelay_disable=eflags& SCTP_FLAG_SACDELAY_DISABLE;
if (sackdelay_enable && sackdelay_disable)
return -1;
if (sackdelay_enable) cflags |= SPP_SACKDELAY_ENABLE;
if (sackdelay_disable) cflags |= SPP_SACKDELAY_DISABLE;
+# endif
arg.pap.spp_flags = cflags;
# endif
@@ -6167,13 +6791,15 @@ static int sctp_fill_opts(inet_descriptor* desc, char* buf, int buflen,
if (ap.spp_flags & SPP_PMTUD_DISABLE)
{ i = LOAD_ATOM (spec, i, am_pmtud_disable); n++; }
-
+# ifdef HAVE_STRUCT_SCTP_PADDRPARAMS_SPP_SACKDELAY
+ /* SPP_SACKDELAY_* not in FreeBSD 7.1 */
if (ap.spp_flags & SPP_SACKDELAY_ENABLE)
{ i = LOAD_ATOM (spec, i, am_sackdelay_enable); n++; }
if (ap.spp_flags & SPP_SACKDELAY_DISABLE)
{ i = LOAD_ATOM (spec, i, am_sackdelay_disable); n++; }
# endif
+# endif
PLACE_FOR(spec, i,
LOAD_NIL_CNT + LOAD_LIST_CNT + 2*LOAD_TUPLE_CNT);
@@ -6193,6 +6819,10 @@ static int sctp_fill_opts(inet_descriptor* desc, char* buf, int buflen,
struct sctp_sndrcvinfo sri;
unsigned int sz = sizeof(sri);
+ if (buflen < ASSOC_ID_LEN) RETURN_ERROR(spec, -EINVAL);
+ sri.sinfo_assoc_id = GET_ASSOC_ID(buf);
+ buf += ASSOC_ID_LEN;
+ buflen -= ASSOC_ID_LEN;
if (sock_getopt(desc->s, IPPROTO_SCTP, SCTP_DEFAULT_SEND_PARAM,
&sri, &sz) < 0) continue;
/* Fill in the response: */
@@ -6640,6 +7270,13 @@ static int inet_ctl(inet_descriptor* desc, int cmd, char* buf, int len,
return inet_ctl_getiflist(desc, rbuf, rsize);
}
+ case INET_REQ_GETIFADDRS: {
+ DEBUGF(("inet_ctl(%ld): GETIFADDRS\r\n", (long)desc->port));
+ if (!IS_OPEN(desc))
+ return ctl_xerror(EXBADPORT, rbuf, rsize);
+ return inet_ctl_getifaddrs(desc, rbuf, rsize);
+ }
+
case INET_REQ_IFGET: {
DEBUGF(("inet_ctl(%ld): IFGET\r\n", (long)desc->port));
if (!IS_OPEN(desc))
@@ -6847,13 +7484,13 @@ static int inet_ctl(inet_descriptor* desc, int cmd, char* buf, int len,
if (len < 2)
return ctl_error(EINVAL, rbuf, rsize);
- n = buf[0]; buf++; len--;
+ n = get_int8(buf); buf++; len--;
if (n >= len) /* the = sign makes the test inklude next length byte */
return ctl_error(EINVAL, rbuf, rsize);
memcpy(namebuf, buf, n);
namebuf[n] = '\0';
len -= n; buf += n;
- n = buf[0]; buf++; len--;
+ n = get_int8(buf); buf++; len--;
if (n > len)
return ctl_error(EINVAL, rbuf, rsize);
memcpy(protobuf, buf, n);
@@ -6876,7 +7513,7 @@ static int inet_ctl(inet_descriptor* desc, int cmd, char* buf, int len,
port = get_int16(buf);
port = sock_htons(port);
buf += 2;
- n = buf[0]; buf++; len -= 3;
+ n = get_int8(buf); buf++; len -= 3;
if (n > len)
return ctl_error(EINVAL, rbuf, rsize);
memcpy(protobuf, buf, n);
diff --git a/erts/emulator/drivers/unix/mem_drv.c b/erts/emulator/drivers/unix/mem_drv.c
deleted file mode 100644
index 1417ca1121..0000000000
--- a/erts/emulator/drivers/unix/mem_drv.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1996-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: Access to elib memory statistics */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "sys.h"
-#include "erl_driver.h"
-#include "elib_stat.h"
-
-#define MAP_BUF_SIZE 1000 /* Max map size */
-#define HISTO_BUF_SIZE 100 /* Max histogram buckets */
-
-static ErlDrvData mem_start(ErlDrvPort);
-static int mem_init(void);
-static void mem_stop(ErlDrvData);
-static void mem_command(ErlDrvData, char*, int);
-
-const struct driver_entry mem_driver_entry = {
- mem_init,
- mem_start,
- mem_stop,
- mem_command,
- NULL,
- NULL,
- "mem_drv"
-};
-
-static int mem_init(void)
-{
- return 0;
-}
-
-static ErlDrvData mem_start(ErlDrvPort port, char* buf)
-{
- return (ErlDrvData)port;
-}
-
-static void mem_stop(ErlDrvData port)
-{
-}
-
-void putint32(p, v)
-byte* p; int v;
-{
- p[0] = (v >> 24) & 0xff;
- p[1] = (v >> 16) & 0xff;
- p[2] = (v >> 8) & 0xff;
- p[3] = (v) & 0xff;
-}
-
-int getint16(p)
-byte* p;
-{
- return (p[0] << 8) | p[1];
-}
-
-/*
-** Command:
-** m L1 L0 -> a heap map of length L1*256 + L0 is returned
-** s -> X3 X2 X1 X0 Y3 Y2 Y1 Y0 Z3 Z2 Z1 Z0
-** X == Total heap size bytes
-** Y == Total free bytes
-** Z == Size of largest free block in bytes
-**
-** h L1 L0 B0 -> Generate a logarithm historgram base B with L buckets
-** l L1 L0 S0 -> Generate a linear histogram with step S with L buckets
-*/
-unsigned char outbuf[HISTO_BUF_SIZE*2*4];
-
-static void mem_command(ErlDrvData port, char* buf, int count)
-{
- if ((count == 1) && buf[0] == 's') {
- struct elib_stat info;
- char v[3*4];
-
- elib_stat(&info);
-
- putint32(v, info.mem_total*4);
- putint32(v+4, info.mem_free*4);
- putint32(v+8, info.max_free*4);
- driver_output((ErlDrvPort)port, v, 12);
- return;
- }
- else if ((count == 3) && buf[0] == 'm') {
- char w[MAP_BUF_SIZE];
- int n = getint16(buf+1);
-
- if (n > MAP_BUF_SIZE)
- n = MAP_BUF_SIZE;
- elib_heap_map(w, n);
- driver_output((ErlDrvPort)port, w, n);
- return;
- }
- else if ((count == 4) && (buf[0] == 'h' || buf[0] == 'l')) {
- unsigned long vf[HISTO_BUF_SIZE];
- unsigned long va[HISTO_BUF_SIZE];
- int n = getint16(buf+1);
- int base = (unsigned char) buf[3];
-
- if (n >= HISTO_BUF_SIZE)
- n = HISTO_BUF_SIZE;
- if (buf[0] == 'l')
- base = -base;
- if (elib_histo(vf, va, n, base) < 0) {
- driver_failure((ErlDrvPort)port, -1);
- return;
- }
- else {
- char* p = outbuf;
- int i;
-
- for (i = 0; i < n; i++) {
- putint32(p, vf[i]);
- p += 4;
- }
- for (i = 0; i < n; i++) {
- putint32(p, va[i]);
- p += 4;
- }
- driver_output((ErlDrvPort)port, outbuf, n*8);
- }
- return;
- }
- driver_failure((ErlDrvPort)port, -1);
-}
diff --git a/erts/emulator/drivers/unix/unix_efile.c b/erts/emulator/drivers/unix/unix_efile.c
index 0052ac0739..b19f632f52 100644
--- a/erts/emulator/drivers/unix/unix_efile.c
+++ b/erts/emulator/drivers/unix/unix_efile.c
@@ -98,7 +98,7 @@ extern STATUS copy(char *, char *);
#define EF_SAFE_REALLOC(P, S) ef_safe_realloc((P), (S))
#define EF_FREE(P) do { if((P)) driver_free((P)); } while(0)
-extern void erl_exit(int n, char *fmt, _DOTS_);
+void erl_exit(int n, char *fmt, ...);
static void *ef_safe_alloc(Uint s)
{
@@ -127,7 +127,7 @@ static void *ef_safe_realloc(void *op, Uint s)
(s[0] == '.' && (s[1] == '\0' || (s[1] == '.' && s[2] == '\0')))
#ifdef VXWORKS
-static FUNCTION(int, vxworks_to_posix, (int vx_errno));
+static int vxworks_to_posix(int vx_errno);
#endif
/*
@@ -146,7 +146,7 @@ static FUNCTION(int, vxworks_to_posix, (int vx_errno));
#define CHECK_PATHLEN(X,Y) /* Nothing */
#endif
-static FUNCTION(int, check_error, (int result, Efile_error* errInfo));
+static int check_error(int result, Efile_error* errInfo);
static int
check_error(int result, Efile_error *errInfo)
diff --git a/erts/emulator/drivers/win32/mem_drv.c b/erts/emulator/drivers/win32/mem_drv.c
deleted file mode 100644
index fa7c46eca8..0000000000
--- a/erts/emulator/drivers/win32/mem_drv.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1997-2009. All Rights Reserved.
- *
- * The contents of this file are subject to the Erlang Public License,
- * Version 1.1, (the "License"); you may not use this file except in
- * compliance with the License. You should have received a copy of the
- * Erlang Public License along with this software. If not, it can be
- * retrieved online at http://www.erlang.org/.
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * %CopyrightEnd%
- */
-/* Purpose: Access to elib memory statistics */
-
-#include "sys.h"
-#include "erl_driver.h"
-#include "elib_stat.h"
-
-#define MAP_BUF_SIZE 1000 /* Max map size */
-#define HISTO_BUF_SIZE 100 /* Max histogram buckets */
-
-static ErlDrvData mem_start(ErlDrvPort, char*);
-static int mem_init(void);
-static void mem_stop(ErlDrvData);
-static void mem_command(ErlDrvData);
-
-ErlDrvEntry mem_driver_entry = {
- mem_init,
- mem_start,
- mem_stop,
- mem_command,
- NULL,
- NULL,
- "mem_drv"
-};
-
-static int mem_init(void)
-{
- return 0;
-}
-
-static ErlDrvData mem_start(ErlDrvPort port, char* buf)
-{
- return (ErlDrvData)port;
-}
-
-static void mem_stop(ErlDrvData port)
-{
-}
-
-void putint32(p, v)
-byte* p; int v;
-{
- p[0] = (v >> 24) & 0xff;
- p[1] = (v >> 16) & 0xff;
- p[2] = (v >> 8) & 0xff;
- p[3] = (v) & 0xff;
-}
-
-int getint16(p)
-byte* p;
-{
- return (p[0] << 8) | p[1];
-}
-
-/*
-** Command:
-** m L1 L0 -> a heap map of length L1*256 + L0 is returned
-** s -> X3 X2 X1 X0 Y3 Y2 Y1 Y0 Z3 Z2 Z1 Z0
-** X == Total heap size bytes
-** Y == Total free bytes
-** Z == Size of largest free block in bytes
-**
-** h L1 L0 B0 -> Generate a logarithm histogram base B with L buckets
-** l L1 L0 S0 -> Generate a linear histogram with step S with L buckets
-*/
-unsigned char outbuf[HISTO_BUF_SIZE*2*4];
-
-static void mem_command(ErlDrvData port, char* buf, int count)
-{
- if ((count == 1) && buf[0] == 's') {
- struct elib_stat info;
- char v[3*4];
-
- elib_stat(&info);
-
- putint32(v, info.mem_total*4);
- putint32(v+4, info.mem_free*4);
- putint32(v+8, info.max_free*4);
- driver_output((ErlDrvPort)port, v, 12);
- return;
- }
- else if ((count == 3) && buf[0] == 'm') {
- char w[MAP_BUF_SIZE];
- int n = getint16(buf+1);
-
- if (n > MAP_BUF_SIZE)
- n = MAP_BUF_SIZE;
- elib_heap_map(w, n);
- driver_output((ErlDrvPort)port, w, n);
- return;
- }
- else if ((count == 4) && (buf[0] == 'h' || buf[0] == 'l')) {
- unsigned long vf[HISTO_BUF_SIZE];
- unsigned long va[HISTO_BUF_SIZE];
- int n = getint16(buf+1);
- int base = (unsigned char) buf[3];
-
- if (n >= HISTO_BUF_SIZE)
- n = HISTO_BUF_SIZE;
- if (buf[0] == 'l')
- base = -base;
- if (elib_histo(vf, va, n, base) < 0) {
- driver_failure((ErlDrvPort)port, -1);
- return;
- }
- else {
- char* p = outbuf;
- int i;
-
- for (i = 0; i < n; i++) {
- putint32(p, vf[i]);
- p += 4;
- }
- for (i = 0; i < n; i++) {
- putint32(p, va[i]);
- p += 4;
- }
- driver_output((ErlDrvPort)port, outbuf, n*8);
- }
- return;
- }
- driver_failure((ErlDrvPort)port, -1);
-}
-
diff --git a/erts/emulator/hipe/hipe_amd64_glue.S b/erts/emulator/hipe/hipe_amd64_glue.S
index 83b7b0397b..3376487292 100644
--- a/erts/emulator/hipe/hipe_amd64_glue.S
+++ b/erts/emulator/hipe/hipe_amd64_glue.S
@@ -346,6 +346,8 @@ nbif_3_gc_after_bif:
subq $(16-8), %rsp
movq P, %rdi
movq %rax, %rsi
+ xorl %edx, %edx # Pass NULL in regs
+ xorl %ecx, %ecx # Pass 0 in arity
call CSYM(erts_gc_after_bif_call)
addq $(16-8), %rsp
movl $0, P_NARITY(P) # Note: narity is a 32-bit field
@@ -400,7 +402,7 @@ nbif_3_simple_exception:
* - the native heap/stack/reds registers are saved in P
*/
.handle_trap:
- movq %rax, P_NARITY(P)
+ movl %eax, P_NARITY(P) # Note: narity is a 32-bit field
movl $HIPE_MODE_SWITCH_RES_TRAP, %eax
jmp .nosave_exit
diff --git a/erts/emulator/hipe/hipe_arm_glue.S b/erts/emulator/hipe/hipe_arm_glue.S
index 5d626a5f69..2bce01954e 100644
--- a/erts/emulator/hipe/hipe_arm_glue.S
+++ b/erts/emulator/hipe/hipe_arm_glue.S
@@ -311,6 +311,8 @@ nbif_3_gc_after_bif:
str TEMP_LR, [P, #P_NRA]
str NSP, [P, #P_NSP]
mov TEMP_LR, lr
+ mov r3, #0 /* Pass 0 in arity */
+ mov r2, #0 /* Pass NULL in regs */
mov r1, r0
mov r0, P
bl erts_gc_after_bif_call
diff --git a/erts/emulator/hipe/hipe_bif0.c b/erts/emulator/hipe/hipe_bif0.c
index b0abfd2310..2a877d8ace 100644
--- a/erts/emulator/hipe/hipe_bif0.c
+++ b/erts/emulator/hipe/hipe_bif0.c
@@ -440,9 +440,12 @@ BIF_RETTYPE hipe_bifs_alloc_data_2(BIF_ALIST_2)
align != sizeof(long) && align != sizeof(double)))
BIF_ERROR(BIF_P, BADARG);
nrbytes = unsigned_val(BIF_ARG_2);
+ if (nrbytes == 0)
+ BIF_RET(make_small(0));
block = erts_alloc(ERTS_ALC_T_HIPE, nrbytes);
if ((unsigned long)block & (align-1))
- fprintf(stderr, "Yikes! erts_alloc() returned misaligned address %p\r\n", block);
+ fprintf(stderr, "%s: erts_alloc(%lu) returned %p which is not %lu-byte aligned\r\n",
+ __FUNCTION__, (unsigned long)nrbytes, block, (unsigned long)align);
BIF_RET(address_to_term(block, BIF_P));
}
diff --git a/erts/emulator/hipe/hipe_bif1.c b/erts/emulator/hipe/hipe_bif1.c
index 5188950e17..8f43811537 100644
--- a/erts/emulator/hipe/hipe_bif1.c
+++ b/erts/emulator/hipe/hipe_bif1.c
@@ -876,22 +876,44 @@ BIF_RETTYPE hipe_bifs_misc_timer_clear_0(BIF_ALIST_0)
* + The fallback, which is the same as {X,_} = runtime(statistics).
*/
+static double fallback_get_hrvtime(void)
+{
+ unsigned long ms_user;
+
+ elapsed_time_both(&ms_user, NULL, NULL, NULL);
+ return (double)ms_user;
+}
+
#if USE_PERFCTR
#include "hipe_perfctr.h"
-static int hrvtime_is_open;
-#define hrvtime_is_started() hrvtime_is_open
+static int hrvtime_started; /* 0: closed, +1: perfctr, -1: fallback */
+#define hrvtime_is_started() (hrvtime_started != 0)
static void start_hrvtime(void)
{
if (hipe_perfctr_hrvtime_open() >= 0)
- hrvtime_is_open = 1;
+ hrvtime_started = 1;
+ else
+ hrvtime_started = -1;
}
-#define get_hrvtime() hipe_perfctr_hrvtime_get()
-#define stop_hrvtime() hipe_perfctr_hrvtime_close()
+static void stop_hrvtime(void)
+{
+ if (hrvtime_started > 0)
+ hipe_perfctr_hrvtime_close();
+ hrvtime_started = 0;
+}
-#else
+static double get_hrvtime(void)
+{
+ if (hrvtime_started > 0)
+ return hipe_perfctr_hrvtime_get();
+ else
+ return fallback_get_hrvtime();
+}
+
+#else /* !USE_PERFCTR */
/*
* Fallback, if nothing better exists.
@@ -902,15 +924,9 @@ static void start_hrvtime(void)
#define hrvtime_is_started() 1
#define start_hrvtime() do{}while(0)
#define stop_hrvtime() do{}while(0)
+#define get_hrvtime() fallback_get_hrvtime()
-static double get_hrvtime(void)
-{
- unsigned long ms_user;
- elapsed_time_both(&ms_user, NULL, NULL, NULL);
- return (double)ms_user;
-}
-
-#endif /* hrvtime support */
+#endif /* !USE_PERFCTR */
BIF_RETTYPE hipe_bifs_get_hrvtime_0(BIF_ALIST_0)
{
@@ -918,11 +934,8 @@ BIF_RETTYPE hipe_bifs_get_hrvtime_0(BIF_ALIST_0)
Eterm res;
FloatDef f;
- if (!hrvtime_is_started()) {
+ if (!hrvtime_is_started())
start_hrvtime();
- if (!hrvtime_is_started())
- BIF_RET(NIL); /* arity 0 BIFs may not fail */
- }
f.fd = get_hrvtime();
hp = HAlloc(BIF_P, FLOAT_SIZE_OBJECT);
res = make_float(hp);
diff --git a/erts/emulator/hipe/hipe_ppc_glue.S b/erts/emulator/hipe/hipe_ppc_glue.S
index 97b07353f9..c010f4f047 100644
--- a/erts/emulator/hipe/hipe_ppc_glue.S
+++ b/erts/emulator/hipe/hipe_ppc_glue.S
@@ -476,6 +476,8 @@ CSYM(nbif_3_gc_after_bif):
STORE TEMP_LR, P_NRA(P)
STORE NSP, P_NSP(P)
mflr TEMP_LR
+ li r6, 0 /* Pass 0 in arity */
+ li r5, 0 /* Pass NULL in regs */
mr r4, r3
mr r3, P
bl CSYM(erts_gc_after_bif_call)
@@ -539,7 +541,7 @@ CSYM(nbif_3_simple_exception):
.handle_trap:
li r3, HIPE_MODE_SWITCH_RES_TRAP
STORE NSP, P_NSP(P)
- STORE r4, P_NARITY(P)
+ stw r4, P_NARITY(P) /* Note: narity is a 32-bit field */
STORE TEMP_LR, P_NRA(P)
b .nosave_exit
diff --git a/erts/emulator/hipe/hipe_sparc_glue.S b/erts/emulator/hipe/hipe_sparc_glue.S
index d1af5c43f5..73cefd4896 100644
--- a/erts/emulator/hipe/hipe_sparc_glue.S
+++ b/erts/emulator/hipe/hipe_sparc_glue.S
@@ -333,6 +333,8 @@ nbif_3_gc_after_bif:
st TEMP_RA, [P+P_NRA]
st NSP, [P+P_NSP]
mov RA, TEMP_RA
+ mov 0, %o3 /* Pass 0 in arity */
+ mov 0, %o2 /* Pass NULL in regs */
mov %o0, %o1
call erts_gc_after_bif_call
mov P, %o0 /* delay slot */
diff --git a/erts/emulator/hipe/hipe_x86_glue.S b/erts/emulator/hipe/hipe_x86_glue.S
index 2f7dff39f5..43392111fe 100644
--- a/erts/emulator/hipe/hipe_x86_glue.S
+++ b/erts/emulator/hipe/hipe_x86_glue.S
@@ -320,11 +320,13 @@ nbif_3_gc_after_bif:
.align 4
.gc_after_bif:
movl %edx, P_NARITY(P)
- subl $(16-4), %esp
+ subl $(32-4), %esp
movl P, (%esp)
movl %eax, 4(%esp)
+ movl $0, 8(%esp) # Pass NULL in regs
+ movl $0, 12(%esp) # Pass 0 in arity
call CSYM(erts_gc_after_bif_call)
- addl $(16-4), %esp
+ addl $(32-4), %esp
movl $0, P_NARITY(P)
ret
diff --git a/erts/emulator/hipe/hipe_x86_signal.c b/erts/emulator/hipe/hipe_x86_signal.c
index a4fff4ce31..0c61e7bf96 100644
--- a/erts/emulator/hipe/hipe_x86_signal.c
+++ b/erts/emulator/hipe/hipe_x86_signal.c
@@ -195,7 +195,7 @@ static void do_init(void)
#define INIT() do { if (!init_done()) do_init(); } while (0)
#endif /* __DARWIN__ */
-#if !defined(__GLIBC__) && !defined(__DARWIN__)
+#if !defined(__GLIBC__) && !defined(__DARWIN__) && !defined(__NetBSD__)
/*
* Assume Solaris/x86 2.8.
* There is a number of sigaction() procedures in libc:
@@ -231,6 +231,7 @@ static void do_init(void)
#define INIT() do { if (!init_done()) do_init(); } while (0)
#endif /* not glibc or darwin */
+#if !defined(__NetBSD__)
/*
* This is our wrapper for sigaction(). sigaction() can be called before
* hipe_signal_init() has been executed, especially when threads support
@@ -253,7 +254,7 @@ static int my_sigaction(int signum, const struct sigaction *act, struct sigactio
}
return __next_sigaction(signum, act, oldact);
}
-
+#endif
/*
* This overrides the C library's core sigaction() procedure, catching
* all its internal calls.
@@ -268,7 +269,7 @@ int __SIGACTION(int signum, const struct sigaction *act, struct sigaction *oldac
/*
* This catches the application's own sigaction() calls.
*/
-#if !defined(__DARWIN__)
+#if !defined(__DARWIN__) && !defined(__NetBSD__)
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
{
return my_sigaction(signum, act, oldact);
@@ -326,7 +327,9 @@ void hipe_signal_init(void)
struct sigaction sa;
int i;
+#ifndef __NetBSD__
INIT();
+#endif
hipe_sigaltstack_init();
diff --git a/erts/emulator/obsolete/driver.h b/erts/emulator/obsolete/driver.h
deleted file mode 100644
index 708fe68e1a..0000000000
--- a/erts/emulator/obsolete/driver.h
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1996-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%
- */
-/*
- * OLD, OBSOLETE include file for erlang driver writers.
- * New drivers should use erl_driver.h instead.
- */
-
-#ifndef __DRIVER_H__
-#define __DRIVER_H__
-
-#include <stdlib.h>
-#include "driver_int.h"
-
-#undef _ANSI_ARGS_
-#undef CONST
-
-#if ((defined(__STDC__) || defined(SABER)) && !defined(NO_PROTOTYPE)) || defined(__cplusplus) || defined(USE_PROTOTYPE)
-# define _USING_PROTOTYPES_ 1
-# define _ANSI_ARGS_(x) x
-# define CONST const
-#else
-# define _ANSI_ARGS_(x) ()
-# define CONST
-#endif
-
-#ifdef __cplusplus
-# define EXTERN extern "C"
-#else
-# define EXTERN extern
-#endif
-
-/* Values for mode arg to driver_select() */
-
-#define DO_READ (1 << 0)
-#define DO_WRITE (1 << 1)
-
-/* Flags for set_port_control_flags() */
-#define PORT_CONTROL_FLAG_BINARY 1
-#define PORT_CONTROL_FLAG_HEAVY 2
-
-/* This macro is used to name a dynamic driver's init function in */
-/* a way that doesn't lead to conflicts. This is crucial when using */
-/* operating systems that has one namespace for all symbols */
-/* (e.g. VxWorks). Example: if you have an dynamic driver C source */
-/* file named echo_drv.c, you use the macro like this: */
-/* int DRIVER_INIT(echo_drv)(void *handle) */
-#if defined(VXWORKS)
-# define DRIVER_INIT(DRIVER_NAME) DRIVER_NAME ## _init
-#elif defined(__WIN32__)
-# define DRIVER_INIT(DRIVER_NAME) __declspec(dllexport) driver_init
-#else
-# define DRIVER_INIT(DRIVER_NAME) driver_init
-#endif
-
-typedef int (*F_PTR)(); /* a function pointer */
-typedef long (*L_PTR)(); /* pointer to a function returning long */
-
-extern int null_func();
-
-/* This structure MUST match Binary in global.h exactly!!! */
-typedef struct driver_binary {
- int orig_size; /* total length of binary */
- char orig_bytes[1]; /* the data (char instead of byte!) */
-} DriverBinary;
-
-typedef struct {
- int vsize; /* length of vectors */
- int size; /* total size in bytes */
- SysIOVec* iov;
- DriverBinary** binv;
-} ErlIOVec;
-
-/*
- * OLD, OBSOLETE driver entry structure.
- */
-
-typedef struct driver_entry {
- F_PTR init; /* called at system start up (no args) */
- L_PTR start; /* called when some one does an open_port
- args: port, command (nul-terminated),
- additional/alternate args for fd/vanilla/spawn driver.
- return value -1 means failure, other
- is saved and passed to the other funcs */
- F_PTR stop; /* called when port is closed, and when the
- emulator is halted - arg: start_return */
- F_PTR output; /* called when we have output from erlang to the port
- args: start_return, buf, buflen */
- F_PTR ready_input; /* called when we have input from one of the driver's
- file descriptors - args: start_return, fd */
- F_PTR ready_output; /* called when output is possible to one of the driver's
- file descriptors - args: start_return, fd */
- char *driver_name; /* name supplied as {driver,Name,Args} to open_port */
-
- F_PTR finish; /* called before unloading (DYNAMIC DRIVERS ONLY) */
- void *handle; /* file handle (DYNAMIC DRIVERS ONLY) */
- F_PTR control; /* "ioctl" for drivers (invoked by port_command/3) */
- F_PTR timeout; /* Reserved */
- F_PTR outputv; /* Reserved */
- F_PTR ready_async; /* Completion routine for driver_async */
- F_PTR padding1[3]; /* pad to match size of modern driver struct */
- int padding2[4]; /* more pad */
- F_PTR padding3[3]; /* even more padding */
-} DriverEntry;
-
-
-/* These are the kernel functions available for driver writers */
-
-EXTERN int driver_select _ANSI_ARGS_((int,int,int,int));
-
-EXTERN int driver_output _ANSI_ARGS_((int, char*, int));
-EXTERN int driver_output2 _ANSI_ARGS_((int, char*, int, char*, int));
-EXTERN int driver_output_binary _ANSI_ARGS_((int, char*, int,
- DriverBinary*, int, int));
-EXTERN int driver_outputv _ANSI_ARGS_((int, char*,int,ErlIOVec*,int));
-
-EXTERN int driver_vec_to_buf _ANSI_ARGS_((ErlIOVec*, char*, int));
-
-EXTERN int driver_set_timer _ANSI_ARGS_((int, unsigned long));
-EXTERN int driver_cancel_timer _ANSI_ARGS_((int));
-
-/*
- * The following functions are used to initiate a close of a port
- * from a driver.
- */
-EXTERN int driver_failure_eof _ANSI_ARGS_((int));
-EXTERN int driver_failure_atom _ANSI_ARGS_((int, char *));
-EXTERN int driver_failure_posix _ANSI_ARGS_((int, int));
-EXTERN int driver_failure _ANSI_ARGS_((int, int));
-EXTERN int driver_exit _ANSI_ARGS_ ((int, int));
-
-EXTERN char* erl_errno_id _ANSI_ARGS_((int error));
-EXTERN void set_busy_port _ANSI_ARGS_((int, int));
-EXTERN void add_driver_entry _ANSI_ARGS_((DriverEntry *));
-EXTERN int remove_driver_entry _ANSI_ARGS_((DriverEntry *));
-EXTERN void set_port_control_flags _ANSI_ARGS_((int, int));
-
-/* Binary interface */
-/* NOTE: DO NOT overwrite a binary with new data (if the data is delivered);
-** since the binary is a shared object it MUST be written once.
-*/
-
-EXTERN DriverBinary* driver_alloc_binary _ANSI_ARGS_((int));
-EXTERN DriverBinary* driver_realloc_binary _ANSI_ARGS_((DriverBinary*, int));
-EXTERN void driver_free_binary _ANSI_ARGS_((DriverBinary*));
-
-
-/* Queue interface */
-EXTERN int driver_enqv _ANSI_ARGS_((int, ErlIOVec*, int));
-EXTERN int driver_pushqv _ANSI_ARGS_((int, ErlIOVec*, int));
-EXTERN int driver_deq _ANSI_ARGS_((int, int));
-EXTERN SysIOVec* driver_peekq _ANSI_ARGS_((int, int*));
-EXTERN int driver_sizeq _ANSI_ARGS_((int));
-EXTERN int driver_enq_bin _ANSI_ARGS_((int, DriverBinary*, int, int));
-EXTERN int driver_enq _ANSI_ARGS_((int, char*, int));
-EXTERN int driver_pushq_bin _ANSI_ARGS_((int, DriverBinary*, int, int));
-EXTERN int driver_pushq _ANSI_ARGS_((int, char*, int));
-
-/* Memory management */
-EXTERN void *driver_alloc _ANSI_ARGS_((size_t));
-EXTERN void *driver_realloc _ANSI_ARGS_((void*, size_t));
-EXTERN void driver_free _ANSI_ARGS_((void*));
-
-/* Shared / dynamic link libraries */
-EXTERN void *driver_dl_open _ANSI_ARGS_((char *));
-EXTERN void *driver_dl_sym _ANSI_ARGS_((void *, char *));
-EXTERN int driver_dl_close _ANSI_ARGS_((void *));
-EXTERN char *driver_dl_error _ANSI_ARGS_((void));
-
-/* Async IO functions */
-EXTERN long driver_async _ANSI_ARGS_((int,
- unsigned int*,
- void (*)(void*),
- void *,
- void (*)(void*)));
-EXTERN int driver_async_cancel _ANSI_ARGS_((long));
-
-EXTERN int driver_lock_driver _ANSI_ARGS_((int));
-
-/* Threads */
-typedef void* erl_mutex_t;
-typedef void* erl_cond_t;
-typedef void* erl_thread_t;
-
-EXTERN erl_mutex_t erts_mutex_create _ANSI_ARGS_((void));
-EXTERN int erts_mutex_destroy _ANSI_ARGS_((erl_mutex_t));
-EXTERN int erts_mutex_lock _ANSI_ARGS_((erl_mutex_t));
-EXTERN int erts_mutex_unlock _ANSI_ARGS_((erl_mutex_t));
-
-EXTERN erl_cond_t erts_cond_create _ANSI_ARGS_((void));
-EXTERN int erts_cond_destroy _ANSI_ARGS_((erl_cond_t));
-EXTERN int erts_cond_signal _ANSI_ARGS_((erl_cond_t));
-EXTERN int erts_cond_broadcast _ANSI_ARGS_((erl_cond_t));
-EXTERN int erts_cond_wait _ANSI_ARGS_((erl_cond_t, erl_mutex_t));
-EXTERN int erts_cond_timedwait _ANSI_ARGS_((erl_cond_t, erl_mutex_t, long));
-
-EXTERN int erts_thread_create _ANSI_ARGS_((erl_thread_t*,
- void* (*func)(void*),
- void* arg,
- int detached));
-EXTERN erl_thread_t erts_thread_self _ANSI_ARGS_((void));
-EXTERN void erts_thread_exit _ANSI_ARGS_((void*));
-EXTERN int erts_thread_join _ANSI_ARGS_((erl_thread_t, void**));
-EXTERN int erts_thread_kill _ANSI_ARGS_((erl_thread_t));
-
-
-typedef unsigned long DriverTermData;
-
-#define TERM_DATA(x) ((DriverTermData) (x))
-
-/* Possible types to send from driver Argument type */
-#define ERL_DRV_NIL ((DriverTermData) 1) /* None */
-#define ERL_DRV_ATOM ((DriverTermData) 2) /* driver_mk_atom(string) */
-#define ERL_DRV_INT ((DriverTermData) 3) /* int */
-#define ERL_DRV_PORT ((DriverTermData) 4) /* driver_mk_port(ix) */
-#define ERL_DRV_BINARY ((DriverTermData) 5) /* ErlDriverBinary*, int */
-#define ERL_DRV_STRING ((DriverTermData) 6) /* char*, int */
-#define ERL_DRV_TUPLE ((DriverTermData) 7) /* int */
-#define ERL_DRV_LIST ((DriverTermData) 8) /* int */
-#define ERL_DRV_STRING_CONS ((DriverTermData) 9) /* char*, int */
-#define ERL_DRV_PID ((DriverTermData) 10) /* driver_connected,... */
-
-/* DriverTermData is the type to use for casts when building
- * terms that should be sent to connected process,
- * for instance a tuple on the form {tcp, Port, [Tag|Binary]}
- *
- * DriverTermData spec[] = {
- * ERL_DRV_ATOM, driver_mk_atom("tcp"),
- * ERL_DRV_PORT, driver_mk_port(drv->ix),
- * ERL_DRV_INT, REPLY_TAG,
- * ERL_DRV_BIN, 50, TERM_DATA(buffer),
- * ERL_DRV_LIST, 2,
- * ERL_DRV_TUPLE, 3,
- * }
- *
- */
-
-EXTERN DriverTermData driver_mk_atom _ANSI_ARGS_ ((char*));
-EXTERN DriverTermData driver_mk_port _ANSI_ARGS_ ((int));
-EXTERN DriverTermData driver_connected _ANSI_ARGS_((int));
-EXTERN DriverTermData driver_caller _ANSI_ARGS_((int));
-
-EXTERN int driver_output_term _ANSI_ARGS_((int, DriverTermData *, int));
-EXTERN int driver_send_term _ANSI_ARGS_((int, DriverTermData, DriverTermData *, int));
-
-#endif
-
-
diff --git a/erts/emulator/sys/common/erl_mseg.c b/erts/emulator/sys/common/erl_mseg.c
index 1c4c37b01a..b1ee165489 100644
--- a/erts/emulator/sys/common/erl_mseg.c
+++ b/erts/emulator/sys/common/erl_mseg.c
@@ -382,6 +382,14 @@ mseg_recreate(void *old_seg, Uint old_size, Uint new_size)
new_seg = (void *) pmremap((void *) old_seg,
(size_t) old_size,
(size_t) new_size);
+#elif defined(__NetBSD__)
+ new_seg = (void *) mremap((void *) old_seg,
+ (size_t) old_size,
+ NULL,
+ (size_t) new_size,
+ 0);
+ if (new_seg == (void *) MAP_FAILED)
+ new_seg = NULL;
#else
new_seg = (void *) mremap((void *) old_seg,
(size_t) old_size,
diff --git a/erts/emulator/sys/common/erl_poll.c b/erts/emulator/sys/common/erl_poll.c
index 09fb6337f7..c17806d96c 100644
--- a/erts/emulator/sys/common/erl_poll.c
+++ b/erts/emulator/sys/common/erl_poll.c
@@ -286,7 +286,7 @@ struct ErtsPollSet_ {
ErtsPollSet next;
int internal_fd_limit;
ErtsFdStatus *fds_status;
- int no_of_user_fds;
+ erts_smp_atomic_t no_of_user_fds;
int fds_status_len;
#if ERTS_POLL_USE_KERNEL_POLL
int kp_fd;
@@ -852,7 +852,7 @@ write_batch_buf(ErtsPollSet ps, ErtsPollBatchBuf *bbp)
ps->fds_status[fd].flags |= ERTS_POLL_FD_FLG_USEFLBCK;
ASSERT(ps->fds_status[fd].used_events);
ps->fds_status[fd].used_events = 0;
- ps->no_of_user_fds--;
+ erts_smp_atomic_dec(&ps->no_of_user_fds);
update_fallback_pollset(ps, fd);
ASSERT(ps->fds_status[fd].flags & ERTS_POLL_FD_FLG_INFLBCK);
break;
@@ -902,11 +902,11 @@ batch_update_pollset(ErtsPollSet ps, int fd, ErtsPollBatchBuf *bbp)
events = ERTS_POLL_EV_E2N(ps->fds_status[fd].events);
if (!events) {
buf[buf_len].events = POLLREMOVE;
- ps->no_of_user_fds--;
+ erts_smp_atomic_dec(&ps->no_of_user_fds);
}
else if (!ps->fds_status[fd].used_events) {
buf[buf_len].events = events;
- ps->no_of_user_fds++;
+ erts_smp_atomic_inc(&ps->no_of_user_fds);
}
else {
if ((ps->fds_status[fd].flags & ERTS_POLL_FD_FLG_RST)
@@ -996,12 +996,12 @@ batch_update_pollset(ErtsPollSet ps, int fd, ErtsPollBatchBuf *bbp)
}
if (used_events) {
if (!events) {
- ps->no_of_user_fds--;
+ erts_smp_atomic_dec(&ps->no_of_user_fds);
}
}
else {
if (events)
- ps->no_of_user_fds++;
+ erts_smp_atomic_inc(&ps->no_of_user_fds);
}
ASSERT((events & ~(ERTS_POLL_EV_IN|ERTS_POLL_EV_OUT)) == 0);
ASSERT((used_events & ~(ERTS_POLL_EV_IN|ERTS_POLL_EV_OUT)) == 0);
@@ -1075,7 +1075,7 @@ update_pollset(ErtsPollSet ps, int fd)
epe.data.fd = epe_templ.data.fd;
res = epoll_ctl(ps->kp_fd, EPOLL_CTL_DEL, fd, &epe);
} while (res != 0 && errno == EINTR);
- ps->no_of_user_fds--;
+ erts_smp_atomic_dec(&ps->no_of_user_fds);
ps->fds_status[fd].used_events = 0;
}
@@ -1083,11 +1083,11 @@ update_pollset(ErtsPollSet ps, int fd)
/* A note on EPOLL_CTL_DEL: linux kernel versions before 2.6.9
need a non-NULL event pointer even though it is ignored... */
op = EPOLL_CTL_DEL;
- ps->no_of_user_fds--;
+ erts_smp_atomic_dec(&ps->no_of_user_fds);
}
else if (!ps->fds_status[fd].used_events) {
op = EPOLL_CTL_ADD;
- ps->no_of_user_fds++;
+ erts_smp_atomic_inc(&ps->no_of_user_fds);
}
else {
op = EPOLL_CTL_MOD;
@@ -1137,7 +1137,7 @@ update_pollset(ErtsPollSet ps, int fd)
/* Fall through ... */
case EPOLL_CTL_ADD: {
ps->fds_status[fd].flags |= ERTS_POLL_FD_FLG_USEFLBCK;
- ps->no_of_user_fds--;
+ erts_smp_atomic_dec(&ps->no_of_user_fds);
#if ERTS_POLL_USE_CONCURRENT_UPDATE
if (!*update_fallback) {
*update_fallback = 1;
@@ -1225,7 +1225,7 @@ static int update_pollset(ErtsPollSet ps, int fd)
#if ERTS_POLL_USE_FALLBACK
ASSERT(ps->fds_status[fd].flags & ERTS_POLL_FD_FLG_INFLBCK);
#endif
- ps->no_of_user_fds--;
+ erts_smp_atomic_dec(&ps->no_of_user_fds);
last_pix = --ps->no_poll_fds;
if (pix != last_pix) {
/* Move last pix to this pix */
@@ -1252,7 +1252,7 @@ static int update_pollset(ErtsPollSet ps, int fd)
ASSERT(!(ps->fds_status[fd].flags & ERTS_POLL_FD_FLG_INFLBCK)
|| fd == ps->kp_fd);
#endif
- ps->no_of_user_fds++;
+ erts_smp_atomic_inc(&ps->no_of_user_fds);
ps->fds_status[fd].pix = pix = ps->no_poll_fds++;
if (pix >= ps->poll_fds_len)
grow_poll_fds(ps, pix);
@@ -1303,7 +1303,7 @@ static int update_pollset(ErtsPollSet ps, int fd)
if (!ps->fds_status[fd].used_events) {
ASSERT(events);
- ps->no_of_user_fds++;
+ erts_smp_atomic_inc(&ps->no_of_user_fds);
#if ERTS_POLL_USE_FALLBACK
ps->no_select_fds++;
ps->fds_status[fd].flags |= ERTS_POLL_FD_FLG_INFLBCK;
@@ -1311,7 +1311,7 @@ static int update_pollset(ErtsPollSet ps, int fd)
}
else if (!events) {
ASSERT(ps->fds_status[fd].used_events);
- ps->no_of_user_fds--;
+ erts_smp_atomic_dec(&ps->no_of_user_fds);
ps->fds_status[fd].events = events;
#if ERTS_POLL_USE_FALLBACK
ps->no_select_fds--;
@@ -1912,7 +1912,8 @@ static ERTS_INLINE int
check_fd_events(ErtsPollSet ps, SysTimeval *tv, int max_res, int *ps_locked)
{
ASSERT(!*ps_locked);
- if (ps->no_of_user_fds == 0 && tv->tv_usec == 0 && tv->tv_sec == 0) {
+ if (erts_smp_atomic_read(&ps->no_of_user_fds) == 0
+ && tv->tv_usec == 0 && tv->tv_sec == 0) {
/* Nothing to poll and zero timeout; done... */
return 0;
}
@@ -1950,7 +1951,7 @@ check_fd_events(ErtsPollSet ps, SysTimeval *tv, int max_res, int *ps_locked)
* the maximum number of file descriptors in the poll set.
*/
struct dvpoll poll_res;
- int nfds = ps->no_of_user_fds;
+ int nfds = (int) erts_smp_atomic_read(&ps->no_of_user_fds);
#ifdef ERTS_SMP
nfds++; /* Wakeup pipe */
#endif
@@ -2228,7 +2229,7 @@ ERTS_POLL_EXPORT(erts_poll_create_pollset)(void)
ps->internal_fd_limit = 0;
ps->fds_status = NULL;
ps->fds_status_len = 0;
- ps->no_of_user_fds = 0;
+ erts_smp_atomic_init(&ps->no_of_user_fds, 0);
#if ERTS_POLL_USE_KERNEL_POLL
ps->kp_fd = -1;
#if ERTS_POLL_USE_EPOLL
@@ -2326,7 +2327,7 @@ ERTS_POLL_EXPORT(erts_poll_create_pollset)(void)
#if ERTS_POLL_USE_FALLBACK
ps->fallback_used = 0;
#endif
- ps->no_of_user_fds = 0; /* Don't count wakeup pipe and fallback fd */
+ erts_smp_atomic_set(&ps->no_of_user_fds, 0); /* Don't count wakeup pipe and fallback fd */
erts_smp_spin_lock(&pollsets_lock);
ps->next = pollsets;
@@ -2472,7 +2473,7 @@ ERTS_POLL_EXPORT(erts_poll_info)(ErtsPollSet ps, ErtsPollInfo *pip)
pip->memory_size = size;
- pip->poll_set_size = ps->no_of_user_fds;
+ pip->poll_set_size = (int) erts_smp_atomic_read(&ps->no_of_user_fds);
#ifdef ERTS_SMP
pip->poll_set_size++; /* Wakeup pipe */
#endif
diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c
index 400ef6c0ce..af4ab693dc 100644
--- a/erts/emulator/sys/unix/sys.c
+++ b/erts/emulator/sys/unix/sys.c
@@ -123,8 +123,6 @@ static ErtsSysReportExit *report_exit_transit_list;
extern int check_async_ready(void);
extern int driver_interrupt(int, int);
-/*EXTERN_FUNCTION(void, increment_time, (int));*/
-/*EXTERN_FUNCTION(int, next_time, (_VOID_));*/
extern void do_break(void);
extern void erl_sys_args(int*, char**);
@@ -221,10 +219,10 @@ static struct fd_data {
} *fd_data; /* indexed by fd */
/* static FUNCTION(int, write_fill, (int, char*, int)); unused? */
-static FUNCTION(void, note_child_death, (int, int));
+static void note_child_death(int, int);
#if CHLDWTHR
-static FUNCTION(void *, child_waiter, (void *));
+static void* child_waiter(void *);
#endif
/********************* General functions ****************************/
@@ -2562,7 +2560,6 @@ extern Preload pre_loaded[];
void erts_sys_alloc_init(void)
{
- elib_ensure_initialized();
}
void *erts_sys_alloc(ErtsAlcType_t t, void *x, Uint sz)
diff --git a/erts/emulator/sys/unix/sys_float.c b/erts/emulator/sys/unix/sys_float.c
index c59c99f65e..6e9376b0f3 100644
--- a/erts/emulator/sys/unix/sys_float.c
+++ b/erts/emulator/sys/unix/sys_float.c
@@ -476,7 +476,7 @@ static int mask_fpe(void)
#endif
-#if (defined(__linux__) && (defined(__i386__) || defined(__x86_64__) || defined(__sparc__) || defined(__powerpc__))) || (defined(__DARWIN__) && (defined(__i386__) || defined(__x86_64__) || defined(__ppc__))) || (defined(__FreeBSD__) && (defined(__x86_64__) || defined(__i386__))) || (defined(__OpenBSD__) && defined(__x86_64__)) || (defined(__sun__) && defined(__x86_64__))
+#if (defined(__linux__) && (defined(__i386__) || defined(__x86_64__) || defined(__sparc__) || defined(__powerpc__))) || (defined(__DARWIN__) && (defined(__i386__) || defined(__x86_64__) || defined(__ppc__))) || (defined(__FreeBSD__) && (defined(__x86_64__) || defined(__i386__))) || ((defined(__NetBSD__) || defined(__OpenBSD__)) && defined(__x86_64__)) || (defined(__sun__) && defined(__x86_64__))
#if defined(__linux__) && defined(__i386__)
#if !defined(X86_FXSR_MAGIC)
@@ -519,6 +519,10 @@ static int mask_fpe(void)
#define mc_pc(mc) ((mc)->mc_rip)
#elif defined(__FreeBSD__) && defined(__i386__)
#define mc_pc(mc) ((mc)->mc_eip)
+#elif defined(__NetBSD__) && defined(__x86_64__)
+#define mc_pc(mc) ((mc)->__gregs[_REG_RIP])
+#elif defined(__NetBSD__) && defined(__i386__)
+#define mc_pc(mc) ((mc)->__gregs[_REG_EIP])
#elif defined(__OpenBSD__) && defined(__x86_64__)
#define mc_pc(mc) ((mc)->sc_rip)
#elif defined(__sun__) && defined(__x86_64__)
@@ -610,6 +614,23 @@ static void fpe_sig_action(int sig, siginfo_t *si, void *puc)
struct env87 *env87 = &savefpu->sv_87.sv_env;
env87->en_sw &= ~0xFF;
}
+#elif defined(__NetBSD__) && defined(__x86_64__)
+ mcontext_t *mc = &uc->uc_mcontext;
+ struct fxsave64 *fxsave = (struct fxsave64 *)&mc->__fpregs;
+ pc = mc_pc(mc);
+ fxsave->fx_mxcsr = 0x1F80;
+ fxsave->fx_fsw &= ~0xFF;
+#elif defined(__NetBSD__) && defined(__i386__)
+ mcontext_t *mc = &uc->uc_mcontext;
+ pc = mc_pc(mc);
+ if (uc->uc_flags & _UC_FXSAVE) {
+ struct envxmm *envxmm = (struct envxmm *)&mc->__fpregs;
+ envxmm->en_mxcsr = 0x1F80;
+ envxmm->en_sw &= ~0xFF;
+ } else {
+ struct env87 *env87 = (struct env87 *)&mc->__fpregs;
+ env87->en_sw &= ~0xFF;
+ }
#elif defined(__OpenBSD__) && defined(__x86_64__)
struct fxsave64 *fxsave = uc->sc_fpstate;
pc = mc_pc(uc);
@@ -799,8 +820,17 @@ sys_chars_to_double(char* buf, double* fp)
}
#ifdef NO_FPE_SIGNALS
- if (errno == ERANGE && (*fp == 0.0 || *fp == HUGE_VAL || *fp == -HUGE_VAL)) {
- return -1;
+ if (errno == ERANGE) {
+ if (*fp == HUGE_VAL || *fp == -HUGE_VAL) {
+ /* overflow, should give error */
+ return -1;
+ } else if (t == s && *fp == 0.0) {
+ /* This should give 0.0 - OTP-7178 */
+ errno = 0;
+
+ } else if (*fp == 0.0) {
+ return -1;
+ }
}
#endif
return 0;
@@ -810,7 +840,9 @@ int
matherr(struct exception *exc)
{
#if !defined(NO_FPE_SIGNALS)
- set_current_fp_exception((unsigned long)__builtin_return_address(0));
+ volatile unsigned long *fpexnp = erts_get_current_fp_exception();
+ if (fpexnp != NULL)
+ *fpexnp = (unsigned long)__builtin_return_address(0);
#endif
return 1;
}
diff --git a/erts/emulator/sys/win32/sys.c b/erts/emulator/sys/win32/sys.c
index 54f71b202d..15d4cd7361 100644
--- a/erts/emulator/sys/win32/sys.c
+++ b/erts/emulator/sys/win32/sys.c
@@ -37,7 +37,7 @@
void erts_sys_init_float(void);
void erl_start(int, char**);
-void erl_exit(int n, char*, _DOTS_);
+void erl_exit(int n, char*, ...);
void erl_error(char*, va_list);
void erl_crash_dump(char*, int, char*, ...);
@@ -67,10 +67,10 @@ static void async_read_file(struct async_io* aio, LPVOID buf, DWORD numToRead);
static int async_write_file(struct async_io* aio, LPVOID buf, DWORD numToWrite);
static int get_overlapped_result(struct async_io* aio,
LPDWORD pBytesRead, BOOL wait);
-static FUNCTION(BOOL, CreateChildProcess, (char *, HANDLE, HANDLE,
- HANDLE, LPHANDLE, BOOL,
- LPVOID, LPTSTR, unsigned,
- char **, int *));
+static BOOL CreateChildProcess(char *, HANDLE, HANDLE,
+ HANDLE, LPHANDLE, BOOL,
+ LPVOID, LPTSTR, unsigned,
+ char **, int *);
static int create_pipe(LPHANDLE, LPHANDLE, BOOL, BOOL);
static int ApplicationType(const char* originalName, char fullPath[MAX_PATH],
BOOL search_in_path, BOOL handle_quotes,
@@ -93,7 +93,7 @@ static erts_smp_mtx_t sys_driver_data_lock;
#define APPL_WIN3X 2
#define APPL_WIN32 3
-static FUNCTION(int, driver_write, (long, HANDLE, byte*, int));
+static int driver_write(long, HANDLE, byte*, int);
static void common_stop(int);
static int create_file_thread(struct async_io* aio, int mode);
#ifdef ERTS_SMP
@@ -2627,7 +2627,6 @@ erts_sys_main_thread(void)
void erts_sys_alloc_init(void)
{
- elib_ensure_initialized();
}
void *erts_sys_alloc(ErtsAlcType_t t, void *x, Uint sz)
@@ -3002,7 +3001,6 @@ erts_sys_pre_init(void)
}
#endif
erts_smp_atomic_init(&sys_misc_mem_sz, 0);
- erts_sys_env_init();
}
void noinherit_std_handle(DWORD type)
@@ -3018,6 +3016,8 @@ void erl_sys_init(void)
{
HANDLE handle;
+ erts_sys_env_init();
+
noinherit_std_handle(STD_OUTPUT_HANDLE);
noinherit_std_handle(STD_INPUT_HANDLE);
noinherit_std_handle(STD_ERROR_HANDLE);
diff --git a/erts/emulator/test/Makefile b/erts/emulator/test/Makefile
index 5ec17a5e2a..a4c02da626 100644
--- a/erts/emulator/test/Makefile
+++ b/erts/emulator/test/Makefile
@@ -75,7 +75,6 @@ MODULES= \
node_container_SUITE \
nofrag_SUITE \
num_bif_SUITE \
- obsolete_SUITE \
op_SUITE \
port_SUITE \
port_bif_SUITE \
diff --git a/erts/emulator/test/distribution_SUITE.erl b/erts/emulator/test/distribution_SUITE.erl
index 7c19274696..79252d0593 100644
--- a/erts/emulator/test/distribution_SUITE.erl
+++ b/erts/emulator/test/distribution_SUITE.erl
@@ -27,6 +27,7 @@
-export([all/1,
ping/1, bulk_send/1, bulk_send_small/1,
bulk_send_big/1,
+ bulk_send_bigbig/1,
local_send/1, local_send_small/1, local_send_big/1,
local_send_legal/1, link_to_busy/1, exit_to_busy/1,
lost_exit/1, link_to_dead/1, link_to_dead_new_node/1,
@@ -50,7 +51,8 @@
-export([sender/3, receiver2/2, dummy_waiter/0, dead_process/0,
roundtrip/1, bounce/1, do_dist_auto_connect/1, inet_rpc_server/1,
dist_parallel_sender/3, dist_parallel_receiver/0,
- dist_evil_parallel_receiver/0]).
+ dist_evil_parallel_receiver/0,
+ sendersender/4, sendersender2/4]).
all(suite) -> [
ping, bulk_send, local_send, link_to_busy, exit_to_busy,
@@ -121,7 +123,7 @@ bulk_send(doc) ->
"the time. This tests that a process that is suspended on a ",
"busy port will eventually be resumed."];
bulk_send(suite) ->
- [bulk_send_small, bulk_send_big].
+ [bulk_send_small, bulk_send_big, bulk_send_bigbig].
bulk_send_small(Config) when is_list(Config) ->
?line bulk_send(64, 32).
@@ -129,6 +131,9 @@ bulk_send_small(Config) when is_list(Config) ->
bulk_send_big(Config) when is_list(Config) ->
?line bulk_send(32, 64).
+bulk_send_bigbig(Config) when is_list(Config) ->
+ ?line bulk_sendsend(32*5, 4).
+
bulk_send(Terms, BinSize) ->
?line Dog = test_server:timetrap(test_server:seconds(30)),
@@ -145,6 +150,53 @@ bulk_send(Terms, BinSize) ->
?line test_server:timetrap_cancel(Dog),
{comment, integer_to_list(trunc(Size/1024/Elapsed+0.5)) ++ " K/s"}.
+bulk_sendsend(Terms, BinSize) ->
+ {Rate1, MonitorCount1} = bulk_sendsend2(Terms, BinSize, 5),
+ {Rate2, MonitorCount2} = bulk_sendsend2(Terms, BinSize, 995),
+ Ratio = if MonitorCount2 == 0 -> MonitorCount1 / 1.0;
+ true -> MonitorCount1 / MonitorCount2
+ end,
+ %% A somewhat arbitrary ratio, but hopefully one that will accomodate
+ %% a wide range of CPU speeds.
+ true = (Ratio > 8.0),
+ {comment,
+ integer_to_list(Rate1) ++ " K/s, " ++
+ integer_to_list(Rate2) ++ " K/s, " ++
+ integer_to_list(MonitorCount1) ++ " monitor msgs, " ++
+ integer_to_list(MonitorCount2) ++ " monitor msgs, " ++
+ float_to_list(Ratio) ++ " monitor ratio"}.
+
+bulk_sendsend2(Terms, BinSize, BusyBufSize) ->
+ ?line Dog = test_server:timetrap(test_server:seconds(30)),
+
+ ?line io:format("Sending ~w binaries, each of size ~w K",
+ [Terms, BinSize]),
+ ?line {ok, NodeRecv} = start_node(bulk_receiver),
+ ?line Recv = spawn(NodeRecv, erlang, apply, [fun receiver/2, [0, 0]]),
+ ?line Bin = list_to_binary(lists:duplicate(BinSize*1024, 253)),
+ ?line Size = Terms*size(Bin),
+
+ %% SLF LEFT OFF HERE.
+ %% When the caller uses small hunks, like 4k via
+ %% bulk_sendsend(32*5, 4), then (on my laptop at least), we get
+ %% zero monitor messages. But if we use "+zdbbl 5", then we
+ %% get a lot of monitor messages. So, if we can count up the
+ %% total number of monitor messages that we get when running both
+ %% default busy size and "+zdbbl 5", and if the 5 case gets
+ %% "many many more" monitor messages, then we know we're working.
+
+ ?line {ok, NodeSend} = start_node(bulk_sender, "+zdbbl " ++ integer_to_list(BusyBufSize)),
+ ?line _Send = spawn(NodeSend, erlang, apply, [fun sendersender/4, [self(), Recv, Bin, Terms]]),
+ ?line {Elapsed, {TermsN, SizeN}, MonitorCount} =
+ receive {sendersender, BigRes} ->
+ BigRes
+ end,
+ ?line stop_node(NodeRecv),
+ ?line stop_node(NodeSend),
+
+ ?line test_server:timetrap_cancel(Dog),
+ {trunc(SizeN/1024/Elapsed+0.5), MonitorCount}.
+
sender(To, _Bin, 0) ->
To ! {done, self()},
receive
@@ -155,6 +207,43 @@ sender(To, Bin, Left) ->
To ! {term, Bin},
sender(To, Bin, Left-1).
+%% Sender process to be run on a slave node
+
+sendersender(Parent, To, Bin, Left) ->
+ erlang:system_monitor(self(), [busy_dist_port]),
+ [spawn(fun() -> sendersender2(To, Bin, Left, false) end) ||
+ _ <- lists:seq(1,1)],
+ {USec, {Res, MonitorCount}} =
+ timer:tc(?MODULE, sendersender2, [To, Bin, Left, true]),
+ Parent ! {sendersender, {USec/1000000, Res, MonitorCount}}.
+
+sendersender2(To, Bin, Left, SendDone) ->
+ sendersender3(To, Bin, Left, SendDone, 0).
+
+sendersender3(To, _Bin, 0, SendDone, MonitorCount) ->
+ if SendDone ->
+ To ! {done, self()};
+ true ->
+ ok
+ end,
+ receive
+ {monitor, _Pid, _Type, _Info} = M ->
+ sendersender3(To, _Bin, 0, SendDone, MonitorCount + 1)
+ after 0 ->
+ if SendDone ->
+ receive
+ Any when is_tuple(Any), size(Any) == 2 ->
+ {Any, MonitorCount}
+ end;
+ true ->
+ exit(normal)
+ end
+ end;
+sendersender3(To, Bin, Left, SendDone, MonitorCount) ->
+ To ! {term, Bin},
+ %%timer:sleep(50),
+ sendersender3(To, Bin, Left-1, SendDone, MonitorCount).
+
%% Receiver process to be run on a slave node.
receiver(Terms, Size) ->
diff --git a/erts/emulator/test/float_SUITE.erl b/erts/emulator/test/float_SUITE.erl
index 102e472ea6..99e9457985 100644
--- a/erts/emulator/test/float_SUITE.erl
+++ b/erts/emulator/test/float_SUITE.erl
@@ -22,7 +22,10 @@
-include("test_server.hrl").
-export([all/1,init_per_testcase/2,fin_per_testcase/2,
- fpe/1,fp_drv/1,fp_drv_thread/1,denormalized/1,match/1,bad_float_unpack/1]).
+ fpe/1,fp_drv/1,fp_drv_thread/1,denormalized/1,match/1,
+ bad_float_unpack/1]).
+-export([otp_7178/1]).
+
init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
Dog = ?t:timetrap(?t:minutes(3)),
@@ -33,7 +36,29 @@ fin_per_testcase(_Func, Config) ->
?t:timetrap_cancel(Dog).
all(suite) ->
- [fpe,fp_drv,fp_drv_thread,denormalized,match,bad_float_unpack].
+ [fpe,
+ fp_drv,
+ fp_drv_thread,
+ otp_7178,
+ denormalized,
+ match,
+ bad_float_unpack].
+
+%%
+%% OTP-7178, list_to_float on very small numbers should give 0.0
+%% instead of exception, i.e. ignore underflow.
+%%
+otp_7178(suite) ->
+ [];
+otp_7178(doc) ->
+ ["test that list_to_float on very small numbers give 0.0"];
+otp_7178(Config) when is_list(Config) ->
+ ?line X = list_to_float("1.0e-325"),
+ ?line true = (X < 0.00000001) and (X > -0.00000001),
+ ?line Y = list_to_float("1.0e-325325325"),
+ ?line true = (Y < 0.00000001) and (Y > -0.00000001),
+ ?line {'EXIT', {badarg,_}} = (catch list_to_float("1.0e83291083210")),
+ ok.
%% Forces floating point exceptions and tests that subsequent, legal,
%% operations are calculated correctly. Original version by Sebastian
diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
index 17f644829f..8489124966 100644
--- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
+++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
@@ -296,6 +296,30 @@ static int test_ulong(ErlNifEnv* env, unsigned long i1)
return 1;
}
+static int test_int64(ErlNifEnv* env, ErlNifSInt64 i1)
+{
+ ErlNifSInt64 i2 = 0;
+ ERL_NIF_TERM int_term = enif_make_int64(env, i1);
+ if (!enif_get_int64(env,int_term, &i2) || i1 != i2) {
+ fprintf(stderr, "test_int64(%ld) ...FAILED i2=%ld\r\n",
+ (long)i1, (long)i2);
+ return 0;
+ }
+ return 1;
+}
+
+static int test_uint64(ErlNifEnv* env, ErlNifUInt64 i1)
+{
+ ErlNifUInt64 i2 = 0;
+ ERL_NIF_TERM int_term = enif_make_uint64(env, i1);
+ if (!enif_get_uint64(env,int_term, &i2) || i1 != i2) {
+ fprintf(stderr, "test_ulong(%lu) ...FAILED i2=%lu\r\n",
+ (unsigned long)i1, (unsigned long)i2);
+ return 0;
+ }
+ return 1;
+}
+
static int test_double(ErlNifEnv* env, double d1)
{
double d2 = 0;
@@ -319,6 +343,8 @@ static ERL_NIF_TERM type_test(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
unsigned uint;
long slong;
unsigned long ulong;
+ ErlNifSInt64 sint64;
+ ErlNifUInt64 uint64;
double d;
ERL_NIF_TERM atom, ref1, ref2;
@@ -352,11 +378,25 @@ static ERL_NIF_TERM type_test(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
slong -= slong / 3 + 1;
} while (slong >= 0);
+ sint64 = ((ErlNifSInt64)1 << 63); /* INT64_MIN */
+ do {
+ if (!test_int64(env,sint64)) {
+ goto error;
+ }
+ sint64 += ~sint64 / 3 + 1;
+ } while (sint64 < 0);
+ sint64 = ((ErlNifUInt64)1 << 63) - 1; /* INT64_MAX */
+ do {
+ if (!test_int64(env,sint64)) {
+ goto error;
+ }
+ sint64 -= sint64 / 3 + 1;
+ } while (sint64 >= 0);
uint = UINT_MAX;
for (;;) {
if (!test_uint(env,uint)) {
-
+ goto error;
}
if (uint == 0) break;
uint -= uint / 3 + 1;
@@ -364,11 +404,19 @@ static ERL_NIF_TERM type_test(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
ulong = ULONG_MAX;
for (;;) {
if (!test_ulong(env,ulong)) {
-
+ goto error;
}
if (ulong == 0) break;
ulong -= ulong / 3 + 1;
}
+ uint64 = (ErlNifUInt64)-1; /* UINT64_MAX */
+ for (;;) {
+ if (!test_uint64(env,uint64)) {
+ goto error;
+ }
+ if (uint64 == 0) break;
+ uint64 -= uint64 / 3 + 1;
+ }
if (MAX_SMALL < INT_MAX) { /* 32-bit */
for (i=-10 ; i <= 10; i++) {
@@ -391,11 +439,18 @@ static ERL_NIF_TERM type_test(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
for (i=-10 ; i < 10; i++) {
if (!test_long(env,MAX_SMALL+i) || !test_ulong(env,MAX_SMALL+i) ||
- !test_long(env,MIN_SMALL+i)) {
+ !test_long(env,MIN_SMALL+i) ||
+ !test_int64(env,MAX_SMALL+i) || !test_uint64(env,MAX_SMALL+i) ||
+ !test_int64(env,MIN_SMALL+i)) {
goto error;
}
+ if (MAX_SMALL < INT_MAX) {
+ if (!test_int(env,MAX_SMALL+i) || !test_uint(env,MAX_SMALL+i) ||
+ !test_int(env,MIN_SMALL+i)) {
+ goto error;
+ }
+ }
}
-
for (d=3.141592e-100 ; d < 1e100 ; d *= 9.97) {
if (!test_double(env,d) || !test_double(env,-d)) {
goto error;
@@ -974,8 +1029,11 @@ static ERL_NIF_TERM make_term_list0(struct make_term_info* mti, int n)
static ERL_NIF_TERM make_term_resource(struct make_term_info* mti, int n)
{
void* resource = enif_alloc_resource(mti->resource_type, 10);
+ ERL_NIF_TERM term;
fill(resource, 10, n);
- return enif_make_resource(mti->dst_env, resource);
+ term = enif_make_resource(mti->dst_env, resource);
+ enif_release_resource(resource);
+ return term;
}
static ERL_NIF_TERM make_term_new_binary(struct make_term_info* mti, int n)
{
diff --git a/erts/emulator/test/obsolete_SUITE.erl b/erts/emulator/test/obsolete_SUITE.erl
deleted file mode 100644
index b191f84ee0..0000000000
--- a/erts/emulator/test/obsolete_SUITE.erl
+++ /dev/null
@@ -1,123 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-
--module(obsolete_SUITE).
--author('[email protected]').
--compile(nowarn_obsolete_guard).
-
--export([all/1]).
-
--export([erl_threads/1]).
-
--include("test_server.hrl").
-
--define(DEFAULT_TIMETRAP_SECS, 240).
-
-all(doc) -> [];
-all(suite) ->
- case catch erlang:system_info({wordsize,external}) of
- 4 -> [erl_threads];
- _ -> {skip, "Only expected to work on true 32-bit architectures"}
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% Testcases %%
-%% %%
-
-erl_threads(suite) -> [];
-erl_threads(doc) -> [];
-erl_threads(Cfg) ->
- ?line case erlang:system_info(threads) of
- true ->
- ?line drv_case(Cfg, erl_threads);
- false ->
- ?line {skip, "Emulator not compiled with threads support"}
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% Internal functions %%
-%% %%
-
-drv_case(Config, CaseName) ->
- drv_case(Config, CaseName, "").
-
-drv_case(Config, CaseName, TimeTrap) when integer(TimeTrap) ->
- drv_case(Config, CaseName, "", TimeTrap);
-drv_case(Config, CaseName, Command) when list(Command) ->
- drv_case(Config, CaseName, Command, ?DEFAULT_TIMETRAP_SECS).
-
-drv_case(Config, CaseName, TimeTrap, Command) when list(Command),
- integer(TimeTrap) ->
- drv_case(Config, CaseName, Command, TimeTrap);
-drv_case(Config, CaseName, Command, TimeTrap) when list(Config),
- atom(CaseName),
- list(Command),
- integer(TimeTrap) ->
- case ?t:os_type() of
- {Family, _} when Family == unix; Family == win32 ->
- ?line run_drv_case(Config, CaseName, Command, TimeTrap);
- SkipOs ->
- ?line {skipped,
- lists:flatten(["Not run on "
- | io_lib:format("~p",[SkipOs])])}
- end.
-
-run_drv_case(Config, CaseName, Command, TimeTrap) ->
- ?line Dog = test_server:timetrap(test_server:seconds(TimeTrap)),
- ?line DataDir = ?config(data_dir,Config),
- case erl_ddll:load_driver(DataDir, CaseName) of
- ok -> ok;
- {error, Error} ->
- io:format("~s\n", [erl_ddll:format_error(Error)]),
- ?line ?t:fail()
- end,
- ?line Port = open_port({spawn, atom_to_list(CaseName)}, []),
- ?line true = is_port(Port),
- ?line Port ! {self(), {command, Command}},
- ?line Result = receive_drv_result(Port, CaseName),
- ?line Port ! {self(), close},
- ?line receive
- {Port, closed} ->
- ok
- end,
- ?line ok = erl_ddll:unload_driver(CaseName),
- ?line test_server:timetrap_cancel(Dog),
- ?line Result.
-
-receive_drv_result(Port, CaseName) ->
- ?line receive
- {print, Port, CaseName, Str} ->
- ?line ?t:format("~s", [Str]),
- ?line receive_drv_result(Port, CaseName);
- {'EXIT', Port, Error} ->
- ?line ?t:fail(Error);
- {'EXIT', error, Error} ->
- ?line ?t:fail(Error);
- {failed, Port, CaseName, Comment} ->
- ?line ?t:fail(Comment);
- {skipped, Port, CaseName, Comment} ->
- ?line {skipped, Comment};
- {succeeded, Port, CaseName, ""} ->
- ?line succeeded;
- {succeeded, Port, CaseName, Comment} ->
- ?line {comment, Comment}
- end.
diff --git a/erts/emulator/test/obsolete_SUITE_data/Makefile.src b/erts/emulator/test/obsolete_SUITE_data/Makefile.src
deleted file mode 100644
index d8e2b861c0..0000000000
--- a/erts/emulator/test/obsolete_SUITE_data/Makefile.src
+++ /dev/null
@@ -1,33 +0,0 @@
-# ``The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved via the world wide web at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
-# AB. All Rights Reserved.''
-#
-# $Id$
-#
-
-TEST_DRVS = erl_threads@dll@
-CC = @CC@
-LD = @LD@
-CFLAGS = @SHLIB_CFLAGS@ -I@erl_include@ @DEFS@
-SHLIB_EXTRA_LDLIBS = testcase_driver@obj@
-
-all: $(TEST_DRVS)
-
-@SHLIB_RULES@
-
-testcase_driver@obj@: testcase_driver.c testcase_driver.h
-$(TEST_DRVS): testcase_driver@obj@
-
-
-
diff --git a/erts/emulator/test/obsolete_SUITE_data/erl_threads.c b/erts/emulator/test/obsolete_SUITE_data/erl_threads.c
deleted file mode 100644
index 27a5163121..0000000000
--- a/erts/emulator/test/obsolete_SUITE_data/erl_threads.c
+++ /dev/null
@@ -1,302 +0,0 @@
-/* ``The contents of this file are subject to the Erlang Public License,
- * Version 1.1, (the "License"); you may not use this file except in
- * compliance with the License. You should have received a copy of the
- * Erlang Public License along with this software. If not, it can be
- * retrieved via the world wide web at http://www.erlang.org/.
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * The Initial Developer of the Original Code is Ericsson Utvecklings AB.
- * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
- * AB. All Rights Reserved.''
- *
- * $Id$
- */
-
-#include "testcase_driver.h"
-
-#ifndef __WIN32__
-
-#define NO_OF_THREADS 2
-
-#include <unistd.h>
-#include <errno.h>
-
-static int die;
-static int cw_passed;
-static int res_tf0;
-static int res_tf1;
-static erl_mutex_t mtx;
-static erl_cond_t cnd;
-static erl_thread_t tid[NO_OF_THREADS];
-static int need_join[NO_OF_THREADS];
-
-typedef struct {
- int n;
-} thr_arg_t;
-
-
-static void *tf0(void *vta)
-{
- int r;
-
- if (((thr_arg_t *) vta)->n != 0)
- goto fail;
-
- r = erts_mutex_lock(mtx);
- if (r != 0) {
- erts_mutex_unlock(mtx);
- goto fail;
- }
-
- r = erts_cond_wait(cnd, mtx);
- if (r != 0 || die) {
- erts_mutex_unlock(mtx);
- goto fail;
- }
-
- cw_passed++;
-
- r = erts_cond_wait(cnd, mtx);
- if (r != 0 || die) {
- erts_mutex_unlock(mtx);
- goto fail;
- }
-
- cw_passed++;
-
- r = erts_mutex_unlock(mtx);
- if (r != 0)
- goto fail;
-
- res_tf0 = 0;
-
- return (void *) &res_tf0;
-
- fail:
- return NULL;
-}
-
-
-static void *tf1(void *vta)
-{
- int r;
-
- if (((thr_arg_t *) vta)->n != 1)
- goto fail;
-
- r = erts_mutex_lock(mtx);
- if (r != 0) {
- erts_mutex_unlock(mtx);
- goto fail;
- }
-
- r = erts_cond_wait(cnd, mtx);
- if (r != 0 || die) {
- erts_mutex_unlock(mtx);
- goto fail;
- }
-
- cw_passed++;
-
- r = erts_cond_wait(cnd, mtx);
- if (r != 0 || die) {
- erts_mutex_unlock(mtx);
- goto fail;
- }
-
- cw_passed++;
-
- r = erts_mutex_unlock(mtx);
- if (r != 0)
- goto fail;
-
- res_tf1 = 1;
-
- erts_thread_exit((void *) &res_tf1);
-
- res_tf1 = 4711;
-
- fail:
- return NULL;
-}
-
-#endif /* #ifndef __WIN32__ */
-
-void
-testcase_run(TestCaseState_t *tcs)
-{
-#ifdef __WIN32__
- testcase_skipped(tcs, "Nothing to test; not supported on windows.");
-#else
- int i, r;
- void *tres[NO_OF_THREADS];
- thr_arg_t ta[NO_OF_THREADS];
- erl_thread_t t1;
-
- die = 0;
- cw_passed = 0;
-
- for (i = 0; i < NO_OF_THREADS; i++)
- need_join[i] = 0;
-
- res_tf0 = 17;
- res_tf1 = 17;
-
- cnd = mtx = NULL;
-
- /* Create mutex and cond */
- mtx = erts_mutex_create();
- ASSERT(tcs, mtx);
- cnd = erts_cond_create();
- ASSERT(tcs, cnd);
-
- /* Create the threads */
- ta[0].n = 0;
- r = erts_thread_create(&tid[0], tf0, (void *) &ta[0], 0);
- ASSERT(tcs, r == 0);
- need_join[0] = 1;
-
- ta[1].n = 1;
- r = erts_thread_create(&tid[1], tf1, (void *) &ta[1], 0);
- ASSERT(tcs, r == 0);
- need_join[1] = 1;
-
- /* Make sure the threads waits on cond wait */
- sleep(1);
-
- r = erts_mutex_lock(mtx);
- ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx));
-
- ASSERT_CLNUP(tcs, cw_passed == 0, (void) erts_mutex_unlock(mtx));
-
-
- /* Let one thread pass one cond wait */
- r = erts_cond_signal(cnd);
- ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx));
-
- r = erts_mutex_unlock(mtx);
- ASSERT(tcs, r == 0);
-
- sleep(1);
-
- r = erts_mutex_lock(mtx);
- ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx));
-
- ASSERT_CLNUP(tcs, cw_passed == 1, (void) erts_mutex_unlock(mtx));
-
-
- /* Let both threads pass one cond wait */
- r = erts_cond_broadcast(cnd);
- ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx));
-
- r = erts_mutex_unlock(mtx);
- ASSERT(tcs, r == 0);
-
- sleep(1);
-
- r = erts_mutex_lock(mtx);
- ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx));
-
- ASSERT_CLNUP(tcs, cw_passed == 3, (void) erts_mutex_unlock(mtx));
-
-
- /* Let the thread that only have passed one cond wait pass the other one */
- r = erts_cond_signal(cnd);
- ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx));
-
- r = erts_mutex_unlock(mtx);
- ASSERT(tcs, r == 0);
-
- sleep(1);
-
- r = erts_mutex_lock(mtx);
- ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx));
-
- ASSERT_CLNUP(tcs, cw_passed == 4, (void) erts_mutex_unlock(mtx));
-
- /* Both threads should have passed both cond waits and exited;
- join them and check returned values */
-
- r = erts_thread_join(tid[0], &tres[0]);
- ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx));
- need_join[0] = 0;
-
- ASSERT_CLNUP(tcs, tres[0] == &res_tf0, (void) erts_mutex_unlock(mtx));
- ASSERT_CLNUP(tcs, res_tf0 == 0, (void) erts_mutex_unlock(mtx));
-
- r = erts_thread_join(tid[1], &tres[1]);
- ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx));
- need_join[1] = 0;
-
- ASSERT_CLNUP(tcs, tres[1] == &res_tf1, (void) erts_mutex_unlock(mtx));
- ASSERT_CLNUP(tcs, res_tf1 == 1, (void) erts_mutex_unlock(mtx));
-
- /* Test signaling when noone waits */
-
- r = erts_cond_signal(cnd);
- ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx));
-
- /* Test broadcasting when noone waits */
-
- r = erts_cond_broadcast(cnd);
- ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx));
-
- /* erts_cond_timedwait() not supported anymore */
- r = erts_cond_timedwait(cnd, mtx, 1000);
- ASSERT_CLNUP(tcs, r != 0, (void) erts_mutex_unlock(mtx));
- ASSERT_CLNUP(tcs,
- strcmp(erl_errno_id(r), "enotsup") == 0,
- (void) erts_mutex_unlock(mtx));
-
- r = erts_mutex_unlock(mtx);
- ASSERT(tcs, r == 0);
-
- r = erts_mutex_destroy(mtx);
- ASSERT(tcs, r == 0);
- mtx = NULL;
-
- r = erts_cond_destroy(cnd);
- ASSERT(tcs, r == 0);
- cnd = NULL;
-
- /* ... */
- t1 = erts_thread_self();
-
- if (cw_passed == 4711) {
- /* We don't want to execute this just check that the
- symbol/symbols is/are defined */
- erts_thread_kill(t1);
- }
-
-#endif /* #ifndef __WIN32__ */
-}
-
-char *
-testcase_name(void)
-{
- return "erl_threads";
-}
-
-void
-testcase_cleanup(TestCaseState_t *tcs)
-{
- int i;
- for (i = 0; i < NO_OF_THREADS; i++) {
- if (need_join[i]) {
- erts_mutex_lock(mtx);
- die = 1;
- erts_cond_broadcast(cnd);
- erts_mutex_unlock(mtx);
- erts_thread_join(tid[1], NULL);
- }
- }
- if (mtx)
- erts_mutex_destroy(mtx);
- if (cnd)
- erts_cond_destroy(cnd);
-}
-
diff --git a/erts/emulator/test/obsolete_SUITE_data/testcase_driver.c b/erts/emulator/test/obsolete_SUITE_data/testcase_driver.c
deleted file mode 100644
index 99d5adb041..0000000000
--- a/erts/emulator/test/obsolete_SUITE_data/testcase_driver.c
+++ /dev/null
@@ -1,262 +0,0 @@
-/* ``The contents of this file are subject to the Erlang Public License,
- * Version 1.1, (the "License"); you may not use this file except in
- * compliance with the License. You should have received a copy of the
- * Erlang Public License along with this software. If not, it can be
- * retrieved via the world wide web at http://www.erlang.org/.
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * The Initial Developer of the Original Code is Ericsson Utvecklings AB.
- * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
- * AB. All Rights Reserved.''
- *
- * $Id$
- */
-
-#include "testcase_driver.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <setjmp.h>
-#include <string.h>
-
-#ifdef __WIN32__
-#undef HAVE_VSNPRINTF
-#define HAVE_VSNPRINTF 1
-#define vsnprintf _vsnprintf
-#endif
-
-#ifndef HAVE_VSNPRINTF
-#define HAVE_VSNPRINTF 0
-#endif
-
-#define COMMENT_BUF_SZ 4096
-
-#define TESTCASE_FAILED 0
-#define TESTCASE_SKIPPED 1
-#define TESTCASE_SUCCEEDED 2
-
-typedef struct {
- TestCaseState_t visible;
- int port;
- int result;
- jmp_buf done_jmp_buf;
- char *comment;
- char comment_buf[COMMENT_BUF_SZ];
-} InternalTestCaseState_t;
-
-long testcase_drv_start(int port, char *command);
-int testcase_drv_stop(long drv_data);
-int testcase_drv_run(long drv_data, char *buf, int len);
-
-static DriverEntry testcase_drv_entry = {
- NULL,
- testcase_drv_start,
- testcase_drv_stop,
- testcase_drv_run
-};
-
-
-int DRIVER_INIT(testcase_drv)(void *arg)
-{
- testcase_drv_entry.driver_name = testcase_name();
- return (int) &testcase_drv_entry;
-}
-
-long
-testcase_drv_start(int port, char *command)
-{
- InternalTestCaseState_t *itcs = (InternalTestCaseState_t *)
- driver_alloc(sizeof(InternalTestCaseState_t));
- if (!itcs) {
- return -1;
- }
-
- itcs->visible.testcase_name = testcase_name();
- itcs->visible.extra = NULL;
- itcs->port = port;
- itcs->result = TESTCASE_FAILED;
- itcs->comment = "";
-
- return (long) itcs;
-}
-
-int
-testcase_drv_stop(long drv_data)
-{
- testcase_cleanup((TestCaseState_t *) drv_data);
- driver_free((void *) drv_data);
- return 0;
-}
-
-int
-testcase_drv_run(long drv_data, char *buf, int len)
-{
- InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) drv_data;
- DriverTermData result_atom;
- DriverTermData msg[12];
-
- itcs->visible.command = buf;
- itcs->visible.command_len = len;
-
- if (setjmp(itcs->done_jmp_buf) == 0) {
- testcase_run((TestCaseState_t *) itcs);
- itcs->result = TESTCASE_SUCCEEDED;
- }
-
- switch (itcs->result) {
- case TESTCASE_SUCCEEDED:
- result_atom = driver_mk_atom("succeeded");
- break;
- case TESTCASE_SKIPPED:
- result_atom = driver_mk_atom("skipped");
- break;
- case TESTCASE_FAILED:
- default:
- result_atom = driver_mk_atom("failed");
- break;
- }
-
- msg[0] = ERL_DRV_ATOM;
- msg[1] = (DriverTermData) result_atom;
-
- msg[2] = ERL_DRV_PORT;
- msg[3] = driver_mk_port(itcs->port);
-
- msg[4] = ERL_DRV_ATOM;
- msg[5] = driver_mk_atom(itcs->visible.testcase_name);
-
- msg[6] = ERL_DRV_STRING;
- msg[7] = (DriverTermData) itcs->comment;
- msg[8] = (DriverTermData) strlen(itcs->comment);
-
- msg[9] = ERL_DRV_TUPLE;
- msg[10] = (DriverTermData) 4;
-
- driver_output_term(itcs->port, msg, 11);
- return 0;
-}
-
-int
-testcase_assertion_failed(TestCaseState_t *tcs,
- char *file, int line, char *assertion)
-{
- testcase_failed(tcs, "%s:%d: Assertion failed: \"%s\"",
- file, line, assertion);
- return 0;
-}
-
-void
-testcase_printf(TestCaseState_t *tcs, char *frmt, ...)
-{
- InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs;
- DriverTermData msg[12];
- va_list va;
- va_start(va, frmt);
-#if HAVE_VSNPRINTF
- vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va);
-#else
- vsprintf(itcs->comment_buf, frmt, va);
-#endif
- va_end(va);
-
- msg[0] = ERL_DRV_ATOM;
- msg[1] = (DriverTermData) driver_mk_atom("print");
-
- msg[2] = ERL_DRV_PORT;
- msg[3] = driver_mk_port(itcs->port);
-
- msg[4] = ERL_DRV_ATOM;
- msg[5] = driver_mk_atom(itcs->visible.testcase_name);
-
- msg[6] = ERL_DRV_STRING;
- msg[7] = (DriverTermData) itcs->comment_buf;
- msg[8] = (DriverTermData) strlen(itcs->comment_buf);
-
- msg[9] = ERL_DRV_TUPLE;
- msg[10] = (DriverTermData) 4;
-
- driver_output_term(itcs->port, msg, 11);
-}
-
-
-void testcase_succeeded(TestCaseState_t *tcs, char *frmt, ...)
-{
- InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs;
- va_list va;
- va_start(va, frmt);
-#if HAVE_VSNPRINTF
- vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va);
-#else
- vsprintf(itcs->comment_buf, frmt, va);
-#endif
- va_end(va);
-
- itcs->result = TESTCASE_SUCCEEDED;
- itcs->comment = itcs->comment_buf;
-
- longjmp(itcs->done_jmp_buf, 1);
-}
-
-void testcase_skipped(TestCaseState_t *tcs, char *frmt, ...)
-{
- InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs;
- va_list va;
- va_start(va, frmt);
-#if HAVE_VSNPRINTF
- vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va);
-#else
- vsprintf(itcs->comment_buf, frmt, va);
-#endif
- va_end(va);
-
- itcs->result = TESTCASE_SKIPPED;
- itcs->comment = itcs->comment_buf;
-
- longjmp(itcs->done_jmp_buf, 1);
-}
-
-void testcase_failed(TestCaseState_t *tcs, char *frmt, ...)
-{
- InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs;
- char buf[10];
- size_t bufsz = sizeof(buf);
- va_list va;
- va_start(va, frmt);
-#if HAVE_VSNPRINTF
- vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va);
-#else
- vsprintf(itcs->comment_buf, frmt, va);
-#endif
- va_end(va);
-
- itcs->result = TESTCASE_FAILED;
- itcs->comment = itcs->comment_buf;
-
- if (erl_drv_getenv("ERL_ABORT_ON_FAILURE", buf, &bufsz) == 0
- && strcmp("true", buf) == 0) {
- fprintf(stderr, "Testcase \"%s\" failed: %s\n",
- itcs->visible.testcase_name, itcs->comment);
- abort();
- }
-
- longjmp(itcs->done_jmp_buf, 1);
-}
-
-void *testcase_alloc(size_t size)
-{
- return driver_alloc(size);
-}
-
-void *testcase_realloc(void *ptr, size_t size)
-{
- return driver_realloc(ptr, size);
-}
-
-void testcase_free(void *ptr)
-{
- driver_free(ptr);
-}
diff --git a/erts/emulator/test/obsolete_SUITE_data/testcase_driver.h b/erts/emulator/test/obsolete_SUITE_data/testcase_driver.h
deleted file mode 100644
index 3d85ca6df0..0000000000
--- a/erts/emulator/test/obsolete_SUITE_data/testcase_driver.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* ``The contents of this file are subject to the Erlang Public License,
- * Version 1.1, (the "License"); you may not use this file except in
- * compliance with the License. You should have received a copy of the
- * Erlang Public License along with this software. If not, it can be
- * retrieved via the world wide web at http://www.erlang.org/.
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * The Initial Developer of the Original Code is Ericsson Utvecklings AB.
- * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
- * AB. All Rights Reserved.''
- *
- * $Id$
- */
-
-#ifndef TESTCASE_DRIVER_H__
-#define TESTCASE_DRIVER_H__
-
-#include "obsolete/driver.h"
-#include <stdlib.h>
-
-typedef struct {
- char *testcase_name;
- char *command;
- int command_len;
- void *extra;
-} TestCaseState_t;
-
-#define ASSERT_CLNUP(TCS, B, CLN) \
-do { \
- if (!(B)) { \
- CLN; \
- testcase_assertion_failed((TCS), __FILE__, __LINE__, #B); \
- } \
-} while (0)
-
-#define ASSERT(TCS, B) ASSERT_CLNUP(TCS, B, (void) 0)
-
-void testcase_printf(TestCaseState_t *tcs, char *frmt, ...);
-void testcase_succeeded(TestCaseState_t *tcs, char *frmt, ...);
-void testcase_skipped(TestCaseState_t *tcs, char *frmt, ...);
-void testcase_failed(TestCaseState_t *tcs, char *frmt, ...);
-int testcase_assertion_failed(TestCaseState_t *tcs, char *file, int line,
- char *assertion);
-void *testcase_alloc(size_t size);
-void *testcase_realloc(void *ptr, size_t size);
-void testcase_free(void *ptr);
-
-
-char *testcase_name(void);
-void testcase_run(TestCaseState_t *tcs);
-void testcase_cleanup(TestCaseState_t *tcs);
-
-#endif
diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl
index 77fa75b78f..a7476ca9bb 100644
--- a/erts/emulator/test/port_SUITE.erl
+++ b/erts/emulator/test/port_SUITE.erl
@@ -2305,7 +2305,11 @@ load_driver(Dir, Driver) ->
close_deaf_port(doc) -> ["Send data to port program that does not read it, then close port."];
close_deaf_port(suite) -> [];
close_deaf_port(Config) when is_list(Config) ->
- Port = open_port({spawn,"sleep 999999"},[]),
- erlang:port_command(Port,"Hello, can you hear me!?!?"),
- port_close(Port),
+ ?line Dog = test_server:timetrap(test_server:seconds(100)),
+ ?line DataDir = ?config(data_dir, Config),
+ ?line DeadPort = os:find_executable("dead_port", DataDir),
+
+ ?line Port = open_port({spawn,DeadPort++" 60"},[]),
+ ?line erlang:port_command(Port,"Hello, can you hear me!?!?"),
+ ?line port_close(Port),
ok.
diff --git a/erts/emulator/test/port_SUITE_data/Makefile.src b/erts/emulator/test/port_SUITE_data/Makefile.src
index d97b37c9ae..ff822ae720 100644
--- a/erts/emulator/test/port_SUITE_data/Makefile.src
+++ b/erts/emulator/test/port_SUITE_data/Makefile.src
@@ -3,7 +3,7 @@ LD = @LD@
CFLAGS = @CFLAGS@ -I@erl_include@ @DEFS@
CROSSLDFLAGS = @CROSSLDFLAGS@
-PROGS = port_test@exe@ echo_args@exe@
+PROGS = port_test@exe@ echo_args@exe@ dead_port@exe@
DRIVERS = echo_drv@dll@ exit_drv@dll@ failure_drv@dll@
all: $(PROGS) $(DRIVERS) port_test.@EMULATOR@
diff --git a/erts/emulator/test/port_SUITE_data/dead_port.c b/erts/emulator/test/port_SUITE_data/dead_port.c
new file mode 100644
index 0000000000..6fa77112be
--- /dev/null
+++ b/erts/emulator/test/port_SUITE_data/dead_port.c
@@ -0,0 +1,102 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2001-2010. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#ifdef VXWORKS
+#include <vxWorks.h>
+#include <taskVarLib.h>
+#include <taskLib.h>
+#include <sysLib.h>
+#include <string.h>
+#include <ioLib.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#ifndef __WIN32__
+#include <unistd.h>
+
+#ifdef VXWORKS
+#include "reclaim.h"
+#include <sys/times.h>
+#else
+#include <sys/time.h>
+#endif
+
+#define O_BINARY 0
+#define _setmode(fd, mode)
+#endif
+
+#ifdef __WIN32__
+#include "windows.h"
+#include "winbase.h"
+#endif
+
+
+#ifdef VXWORKS
+#define MAIN(argc, argv) port_test(argc, argv)
+#else
+#define MAIN(argc, argv) main(argc, argv)
+#endif
+
+
+extern int errno;
+
+static void delay(unsigned ms);
+
+
+MAIN(argc, argv)
+int argc;
+char *argv[];
+{
+ int x;
+ if (argc < 2) {
+ fprintf(stderr,"Usage %s <seconds>\n",argv[0]);
+ return 1;
+ }
+ if ((x = atoi(argv[1])) <= 0) {
+ fprintf(stderr,"Usage %s <seconds>\n",argv[0]);
+ return 1;
+ }
+ delay(x*1000);
+ return 0;
+}
+
+static void
+delay(unsigned ms)
+{
+#ifdef VXWORKS
+ taskDelay((sysClkRateGet() * ms) / 1000);
+#else
+#ifdef __WIN32__
+ Sleep(ms);
+#else
+ struct timeval t;
+ t.tv_sec = ms/1000;
+ t.tv_usec = (ms % 1000) * 1000;
+
+ select(0, NULL, NULL, NULL, &t);
+#endif
+#endif
+}
diff --git a/erts/emulator/test/scheduler_SUITE.erl b/erts/emulator/test/scheduler_SUITE.erl
index 4f4458802c..06442bfad6 100644
--- a/erts/emulator/test/scheduler_SUITE.erl
+++ b/erts/emulator/test/scheduler_SUITE.erl
@@ -47,6 +47,7 @@
scheduler_bind/1,
scheduler_bind_types/1,
cpu_topology/1,
+ update_cpu_info/1,
sct_cmd/1,
sbt_cmd/1,
scheduler_suspend/1,
@@ -249,6 +250,7 @@ bound_loop(NS, N, M, Sched) ->
scheduler_bind(suite) ->
[scheduler_bind_types,
cpu_topology,
+ update_cpu_info,
sct_cmd,
sbt_cmd].
@@ -772,6 +774,137 @@ cpu_topology_cmdline_test(Config, Topology, Cmd) ->
?line stop_node(Node),
?line ok.
+update_cpu_info(Config) when is_list(Config) ->
+ ?line OldOnline = erlang:system_info(schedulers_online),
+ ?line OldAff = get_affinity_mask(),
+ ?line ?t:format("START - Affinity mask: ~p - Schedulers online: ~p - Scheduler bindings: ~p~n",
+ [OldAff, OldOnline, erlang:system_info(scheduler_bindings)]),
+ ?line case {erlang:system_info(logical_processors_available), OldAff} of
+ {Avail, _} when Avail == unknown; OldAff == unknown ->
+ %% Nothing much to test; just a smoke test
+ case erlang:system_info(update_cpu_info) of
+ unchanged -> ?line ok;
+ changed -> ?line ok
+ end;
+ _ ->
+ try
+ ?line adjust_schedulers_online(),
+ case erlang:system_info(schedulers_online) of
+ 1 ->
+ %% Nothing much to test; just a smoke test
+ ?line ok;
+ Onln0 ->
+ %% unset least significant bit
+ ?line Aff = (OldAff band (OldAff - 1)),
+ ?line set_affinity_mask(Aff),
+ ?line Onln1 = Onln0 - 1,
+ ?line case adjust_schedulers_online() of
+ {Onln0, Onln1} ->
+ ?line Onln1 = erlang:system_info(schedulers_online),
+ ?line receive after 500 -> ok end,
+ ?line ?t:format("TEST - Affinity mask: ~p - Schedulers online: ~p - Scheduler bindings: ~p~n",
+ [Aff, Onln1, erlang:system_info(scheduler_bindings)]),
+ ?line unchanged = adjust_schedulers_online(),
+ ?line ok;
+ Fail ->
+ ?line ?t:fail(Fail)
+ end
+ end
+ after
+ set_affinity_mask(OldAff),
+ adjust_schedulers_online(),
+ erlang:system_flag(schedulers_online, OldOnline),
+ receive after 500 -> ok end,
+ ?t:format("END - Affinity mask: ~p - Schedulers online: ~p - Scheduler bindings: ~p~n",
+ [get_affinity_mask(),
+ erlang:system_info(schedulers_online),
+ erlang:system_info(scheduler_bindings)])
+ end
+ end.
+
+adjust_schedulers_online() ->
+ case erlang:system_info(update_cpu_info) of
+ unchanged ->
+ unchanged;
+ changed ->
+ Avail = erlang:system_info(logical_processors_available),
+ {erlang:system_flag(schedulers_online, Avail), Avail}
+ end.
+
+read_affinity(Data) ->
+ Exp = "pid " ++ os:getpid() ++ "'s current affinity mask",
+ case string:tokens(Data, ":") of
+ [Exp, DirtyAffinityStr] ->
+ AffinityStr = string:strip(string:strip(DirtyAffinityStr,
+ both, $ ),
+ both, $\n),
+ case catch erlang:list_to_integer(AffinityStr, 16) of
+ Affinity when is_integer(Affinity) ->
+ Affinity;
+ _ ->
+ bad
+ end;
+ _ ->
+ bad
+ end.
+
+get_affinity_mask(Port, Status, Affinity) when Status == unknown;
+ Affinity == unknown ->
+ receive
+ {Port,{data, Data}} ->
+ get_affinity_mask(Port, Status, read_affinity(Data));
+ {Port,{exit_status,S}} ->
+ get_affinity_mask(Port, S, Affinity)
+ end;
+get_affinity_mask(Port, Status, bad) ->
+ unknown;
+get_affinity_mask(Port, Status, Affinity) ->
+ Affinity.
+
+get_affinity_mask() ->
+ case ?t:os_type() of
+ {unix, linux} ->
+ case catch open_port({spawn, "taskset -p " ++ os:getpid()},
+ [exit_status]) of
+ Port when is_port(Port) ->
+ get_affinity_mask(Port, unknown, unknown);
+ _ ->
+ unknown
+ end;
+ _ ->
+ unknown
+ end.
+
+set_affinity_mask(Port, unknown) ->
+ receive
+ {Port,{data, _}} ->
+ set_affinity_mask(Port, unknown);
+ {Port,{exit_status,Status}} ->
+ set_affinity_mask(Port, Status)
+ end;
+set_affinity_mask(Port, Status) ->
+ receive
+ {Port,{data, _}} ->
+ set_affinity_mask(Port, unknown)
+ after 0 ->
+ Status
+ end.
+
+set_affinity_mask(Mask) ->
+ Cmd = lists:flatten(["taskset -p ",
+ io_lib:format("~.16b", [Mask]),
+ " ",
+ os:getpid()]),
+ case catch open_port({spawn, Cmd}, [exit_status]) of
+ Port when is_port(Port) ->
+ case set_affinity_mask(Port, unknown) of
+ 0 -> ok;
+ _ -> exit(failed_to_set_affinity)
+ end;
+ _ ->
+ exit(failed_to_set_affinity)
+ end.
+
sct_cmd(Config) when is_list(Config) ->
?line Topology = ?TOPOLOGY_A_TERM,
?line OldRelFlags = clear_erl_rel_flags(),
diff --git a/erts/emulator/test/send_term_SUITE.erl b/erts/emulator/test/send_term_SUITE.erl
index 5fd01a9ac5..819aa34886 100644
--- a/erts/emulator/test/send_term_SUITE.erl
+++ b/erts/emulator/test/send_term_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -61,7 +61,7 @@ basic(Config) when is_list(Config) ->
?line ExpectExt2Term = term(P, 5),
%% ERL_DRV_INT, ERL_DRV_UINT
- ?line case erlang:system_info(wordsize) of
+ ?line case erlang:system_info({wordsize, external}) of
4 ->
?line {-1, 4294967295} = term(P, 6);
8 ->
diff --git a/erts/emulator/test/system_info_SUITE.erl b/erts/emulator/test/system_info_SUITE.erl
index ba433d4e11..cd940f3ddf 100644
--- a/erts/emulator/test/system_info_SUITE.erl
+++ b/erts/emulator/test/system_info_SUITE.erl
@@ -132,6 +132,7 @@ misc_smoke_tests(Config) when is_list(Config) ->
?line true = is_binary(erlang:system_info(procs)),
?line true = is_binary(erlang:system_info(loaded)),
?line true = is_binary(erlang:system_info(dist)),
+ ?line ok = try erlang:system_info({cpu_topology,erts_get_cpu_topology_error_case}), fail catch error:badarg -> ok end,
?line ok.
diff --git a/erts/emulator/test/time_SUITE.erl b/erts/emulator/test/time_SUITE.erl
index 2ad1f0d201..095e9dd1af 100644
--- a/erts/emulator/test/time_SUITE.erl
+++ b/erts/emulator/test/time_SUITE.erl
@@ -34,6 +34,8 @@
consistency/1,
now/1, now_unique/1, now_update/1, timestamp/1]).
+-export([local_to_univ_utc/1]).
+
-include("test_server.hrl").
-export([linear_time/1]).
@@ -53,7 +55,40 @@
-define(dst_timezone, 2).
all(suite) -> [univ_to_local, local_to_univ,
- bad_univ_to_local, bad_local_to_univ, consistency, now, timestamp].
+ local_to_univ_utc,
+ bad_univ_to_local, bad_local_to_univ,
+ consistency, now, timestamp].
+
+local_to_univ_utc(suite) ->
+ [];
+local_to_univ_utc(doc) ->
+ ["Test that DST = true on timezones without DST is ignored"];
+local_to_univ_utc(Config) when is_list(Config) ->
+ case os:type() of
+ {unix,_} ->
+ %% TZ variable has a meaning
+ ?line {ok, Node} =
+ test_server:start_node(local_univ_utc,peer,
+ [{args, "-env TZ UTC"}]),
+ ?line {{2008,8,1},{0,0,0}} =
+ rpc:call(Node,
+ erlang,localtime_to_universaltime,
+ [{{2008, 8, 1}, {0, 0, 0}},
+ false]),
+ ?line {{2008,8,1},{0,0,0}} =
+ rpc:call(Node,
+ erlang,localtime_to_universaltime,
+ [{{2008, 8, 1}, {0, 0, 0}},
+ true]),
+ ?line [{{2008,8,1},{0,0,0}}] =
+ rpc:call(Node,
+ calendar,local_time_to_universal_time_dst,
+ [{{2008, 8, 1}, {0, 0, 0}}]),
+ ?line test_server:stop_node(Node),
+ ok;
+ _ ->
+ {skip,"Only valid on Unix"}
+ end.
%% Tests conversion from univeral to local time.
diff --git a/erts/epmd/src/Makefile.in b/erts/epmd/src/Makefile.in
index 498756b468..2f5296a5e8 100644
--- a/erts/epmd/src/Makefile.in
+++ b/erts/epmd/src/Makefile.in
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1998-2009. All Rights Reserved.
+# Copyright Ericsson AB 1998-2010. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -49,15 +49,31 @@ include ../epmd.mk
BINDIR = $(ERL_TOP)/bin/$(TARGET)
OBJDIR = $(ERL_TOP)/erts/obj$(TYPEMARKER)/$(TARGET)
+ERTS_INCL = -I$(ERL_TOP)/erts/include \
+ -I$(ERL_TOP)/erts/include/$(TARGET) \
+ -I$(ERL_TOP)/erts/include/internal \
+ -I$(ERL_TOP)/erts/include/internal/$(TARGET)
+
+# On windows we always need reentrant libraries.
+ifeq ($(TARGET),win32)
+ERTS_INTERNAL_LIBS=-L../../lib/internal/$(TARGET) -lerts_internal_r$(ERTS_LIB_TYPEMARKER) @ERTS_INTERNAL_X_LIBS@
+else
+ifeq ($(findstring vxworks,$(TARGET)),vxworks)
+ERTS_INTERNAL_LIBS=-L../../lib/internal/$(TARGET) -lerts_internal$(ERTS_LIB_TYPEMARKER) @ERTS_INTERNAL_X_LIBS@
+else
+ERTS_INTERNAL_LIBS=-L../../lib/internal/$(TARGET) -lerts_internal$(ERTS_LIB_TYPEMARKER) @ERTS_INTERNAL_X_LIBS@ -lm
+endif
+endif
CC = @CC@
WFLAGS = @WFLAGS@
-CFLAGS = @CFLAGS@ @DEFS@ $(TYPE_FLAGS) $(WFLAGS)
+CFLAGS = @CFLAGS@ @DEFS@ $(TYPE_FLAGS) $(WFLAGS) $(ERTS_INCL)
LD = @LD@
-LIBS = @LIBS@
+LIBS = @LIBS@ $(ERTS_INTERNAL_LIBS)
LDFLAGS = @LDFLAGS@
+
# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
@@ -90,7 +106,7 @@ EPMD_OBJS = $(OBJDIR)/epmd.o \
#---------------------------------
-all: $(BINDIR)/$(EPMD)
+all: erts_lib $(BINDIR)/$(EPMD)
docs:
@@ -109,9 +125,12 @@ clean:
$(BINDIR)/$(EPMD): $(EPMD_OBJS)
$(PURIFY) $(LD) $(LDFLAGS) -o $@ $(EPMD_OBJS) $(LIBS)
-$(OBJDIR)/%.o: %.c
+$(OBJDIR)/%.o: %.c epmd.h epmd_int.h
$(CC) $(CFLAGS) $(EPMD_FLAGS) -o $@ -c $<
+erts_lib:
+ cd $(ERL_TOP)/erts/lib_src && $(MAKE) $(TYPE)
+
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: all
diff --git a/erts/epmd/src/epmd.c b/erts/epmd/src/epmd.c
index 6ddf30efe3..65ff0cd6b2 100644
--- a/erts/epmd/src/epmd.c
+++ b/erts/epmd/src/epmd.c
@@ -23,6 +23,7 @@
#endif
#include "epmd.h" /* Renamed from 'epmd_r4.h' */
#include "epmd_int.h"
+#include "erl_printf.h"
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
@@ -33,6 +34,7 @@
static void usage(EpmdVars *);
static void run_daemon(EpmdVars*);
static int get_port_no(void);
+static int check_relaxed(void);
#ifdef __WIN32__
static int has_console(void);
#endif
@@ -161,6 +163,7 @@ int main(int argc, char** argv)
g->silent = 0;
g->is_daemon = 0;
+ g->brutal_kill = check_relaxed();
g->packet_timeout = CLOSE_TIMEOUT; /* Default timeout */
g->delay_accept = 0;
g->delay_write = 0;
@@ -196,6 +199,9 @@ int main(int argc, char** argv)
} else if (strcmp(argv[0], "-daemon") == 0) {
g->is_daemon = 1;
argv++; argc--;
+ } else if (strcmp(argv[0], "-relaxed_command_check") == 0) {
+ g->brutal_kill = 1;
+ argv++; argc--;
} else if (strcmp(argv[0], "-kill") == 0) {
if (argc == 1)
kill_epmd(g);
@@ -236,7 +242,7 @@ int main(int argc, char** argv)
else
usage(g);
}
- dbg_printf(g,0,"epmd running - daemon = %d",g->is_daemon);
+ dbg_printf(g,1,"epmd running - daemon = %d",g->is_daemon);
#ifndef NO_SYSCONF
if ((g->max_conn = sysconf(_SC_OPEN_MAX)) <= 0)
@@ -388,9 +394,10 @@ static void run_daemon(EpmdVars *g)
static void usage(EpmdVars *g)
{
fprintf(stderr, "usage: epmd [-d|-debug] [DbgExtra...] [-port No] [-daemon]\n");
- fprintf(stderr, " [-d|-debug] [-port No] [-names|-kill|-stop name]\n\n");
- fprintf(stderr, "See the Erlang epmd manual page for info about the usage.\n");
- fprintf(stderr, "The -port and DbgExtra options are\n\n");
+ fprintf(stderr, " [-relaxed_command_check]\n");
+ fprintf(stderr, " epmd [-d|-debug] [-port No] [-names|-kill|-stop name]\n\n");
+ fprintf(stderr, "See the Erlang epmd manual page for info about the usage.\n\n");
+ fprintf(stderr, "Regular options\n");
fprintf(stderr, " -port No\n");
fprintf(stderr, " Let epmd listen to another port than default %d\n",
EPMD_PORT_NO);
@@ -400,8 +407,16 @@ static void usage(EpmdVars *g)
fprintf(stderr, " the standard error stream. It will shorten\n");
fprintf(stderr, " the number of saved used node names to 5.\n\n");
fprintf(stderr, " If you give more than one debug flag you may\n");
- fprintf(stderr, " get more debugging information.\n\n");
- fprintf(stderr, " -packet_timout Seconds\n");
+ fprintf(stderr, " get more debugging information.\n");
+ fprintf(stderr, " -daemon\n");
+ fprintf(stderr, " Start epmd detached (as a daemon)\n");
+ fprintf(stderr, " -relaxed_command_check\n");
+ fprintf(stderr, " Allow this instance of epmd to be killed with\n");
+ fprintf(stderr, " epmd -kill even if there "
+ "are registered nodes.\n");
+ fprintf(stderr, " Also allows forced unregister (epmd -stop).\n");
+ fprintf(stderr, "\nDbgExtra options\n");
+ fprintf(stderr, " -packet_timeout Seconds\n");
fprintf(stderr, " Set the number of seconds a connection can be\n");
fprintf(stderr, " inactive before epmd times out and closes the\n");
fprintf(stderr, " connection (default 60).\n\n");
@@ -413,6 +428,18 @@ static void usage(EpmdVars *g)
fprintf(stderr, " -delay_write Seconds\n");
fprintf(stderr, " Also a simulation of a busy server. Inserts\n");
fprintf(stderr, " a delay before a reply is sent.\n");
+ fprintf(stderr, "\nInteractive options\n");
+ fprintf(stderr, " -names\n");
+ fprintf(stderr, " List names registered with the currently "
+ "running epmd\n");
+ fprintf(stderr, " -kill\n");
+ fprintf(stderr, " Kill the currently runniing epmd\n");
+ fprintf(stderr, " (only allowed if -names show empty database or\n");
+ fprintf(stderr, " -relaxed_command_check was given when epmd was started).\n");
+ fprintf(stderr, " -stop Name\n");
+ fprintf(stderr, " Forcibly unregisters a name with epmd\n");
+ fprintf(stderr, " (only allowed if -relaxed_command_check was given when \n");
+ fprintf(stderr, " epmd was started).\n");
epmd_cleanup_exit(g,1);
}
@@ -432,20 +459,20 @@ static void usage(EpmdVars *g)
* args... Arguments to print out according to the format
*
*/
-
+#define DEBUG_BUFFER_SIZE 2048
static void dbg_gen_printf(int onsyslog,int perr,int from_level,
EpmdVars *g,const char *format, va_list args)
{
time_t now;
char *timestr;
- char buf[2048];
+ char buf[DEBUG_BUFFER_SIZE];
if (g->is_daemon)
{
#ifndef NO_SYSLOG
if (onsyslog)
{
- vsprintf(buf, format, args);
+ erts_vsnprintf(buf, DEBUG_BUFFER_SIZE, format, args);
syslog(LOG_ERR,"epmd: %s",buf);
}
#endif
@@ -456,9 +483,10 @@ static void dbg_gen_printf(int onsyslog,int perr,int from_level,
time(&now);
timestr = (char *)ctime(&now);
- sprintf(buf, "epmd: %.*s: ", (int) strlen(timestr)-1, timestr);
+ erts_snprintf(buf, DEBUG_BUFFER_SIZE, "epmd: %.*s: ",
+ (int) strlen(timestr)-1, timestr);
len = strlen(buf);
- vsprintf(buf + len, format, args);
+ erts_vsnprintf(buf + len, DEBUG_BUFFER_SIZE - len, format, args);
if (perr == 1)
perror(buf);
else
@@ -545,4 +573,9 @@ static int get_port_no(void)
char* port_str = getenv("ERL_EPMD_PORT");
return (port_str != NULL) ? atoi(port_str) : EPMD_PORT_NO;
}
+static int check_relaxed(void)
+{
+ char* port_str = getenv("ERL_EPMD_RELAXED_COMMAND_CHECK");
+ return (port_str != NULL) ? 1 : 0;
+}
diff --git a/erts/epmd/src/epmd.h b/erts/epmd/src/epmd.h
index 9e939ee38e..5d6e9ac165 100644
--- a/erts/epmd/src/epmd.h
+++ b/erts/epmd/src/epmd.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2010. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -17,21 +17,18 @@
* %CopyrightEnd%
*/
-/* The port number is now defined in a makefile */
+/* The port number is defined in a makefile */
/* Definitions of message codes */
-#define EPMD_ALIVE_REQ 'a'
-#define EPMD_ALIVE_OK_RESP 'Y'
-#define EPMD_PORT_REQ 'p'
+/* Registration and queries */
+#define EPMD_ALIVE2_REQ 'x'
+#define EPMD_PORT2_REQ 'z'
+#define EPMD_ALIVE2_RESP 'y'
+#define EPMD_PORT2_RESP 'w'
#define EPMD_NAMES_REQ 'n'
+
+/* Interactive client command codes */
#define EPMD_DUMP_REQ 'd'
#define EPMD_KILL_REQ 'k'
#define EPMD_STOP_REQ 's'
-
-/* New epmd messages */
-
-#define EPMD_ALIVE2_REQ 'x' /* 120 */
-#define EPMD_PORT2_REQ 'z' /* 122 */
-#define EPMD_ALIVE2_RESP 'y' /* 121 */
-#define EPMD_PORT2_RESP 'w' /* 119 */
diff --git a/erts/epmd/src/epmd_cli.c b/erts/epmd/src/epmd_cli.c
index 2aed861390..7c60ba0420 100644
--- a/erts/epmd/src/epmd_cli.c
+++ b/erts/epmd/src/epmd_cli.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2010. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -42,7 +42,11 @@ void kill_epmd(EpmdVars *g)
epmd_cleanup_exit(g,1);
}
if ((rval = read_fill(fd,buf,2)) == 2) {
- printf("Killed\n");
+ if (buf[0] == 'O' && buf[1] == 'K') {
+ printf("Killed\n");
+ } else {
+ printf("Killing not allowed - living nodes in database.\n");
+ }
epmd_cleanup_exit(g,0);
} else if (rval < 0) {
printf("epmd: failed to read answer from local epmd\n");
diff --git a/erts/epmd/src/epmd_int.h b/erts/epmd/src/epmd_int.h
index 5ead553f36..c2558d52a1 100644
--- a/erts/epmd/src/epmd_int.h
+++ b/erts/epmd/src/epmd_int.h
@@ -1,3 +1,4 @@
+/* -*- c-indent-level: 2; c-continued-statement-offset: 2 -*- */
/*
* %CopyrightBegin%
*
@@ -245,8 +246,10 @@
typedef struct {
int fd; /* File descriptor */
- unsigned open:1; /* TRUE if open */
- unsigned keep:1; /* Don't close when sent reply */
+ unsigned char open; /* TRUE if open */
+ unsigned char keep; /* Don't close when sent reply */
+ unsigned char local_peer; /* The peer of this connection is via
+ loopback interface */
unsigned got; /* # of bytes we have got */
unsigned want; /* Number of bytes we want */
char *buf; /* The remaining buffer */
@@ -286,6 +289,7 @@ typedef struct {
int debug;
int silent;
int is_daemon;
+ int brutal_kill;
unsigned packet_timeout;
unsigned delay_accept;
unsigned delay_write;
@@ -307,6 +311,7 @@ void epmd_call(EpmdVars*,int);
void run(EpmdVars*);
void epmd_cleanup_exit(EpmdVars*, int);
int epmd_conn_close(EpmdVars*,Connection*);
+void stop_cli(EpmdVars *g, char *name);
#ifdef DONT_USE_MAIN
int start_epmd(char *,char *,char *,char *,char *,char *,char *,char *,char *,char *);
diff --git a/erts/epmd/src/epmd_srv.c b/erts/epmd/src/epmd_srv.c
index c836bf0bb7..ef471a473a 100644
--- a/erts/epmd/src/epmd_srv.c
+++ b/erts/epmd/src/epmd_srv.c
@@ -39,46 +39,16 @@
* server keeps the socket open where the request for registration was
* made.
*
- * The protocol is briefly documented in "erl_ext_dist.txt". All requests
- * to this server are done with a packet
+ * The protocol is briefly documented in the ERTS User's Guide, see
+ * http://www.erlang.org/doc/apps/erts/erl_dist_protocol.html
+ *
+ * All requests to this server are done with a packet
*
* 2 n
* +--------+---------+
* | Length | Request |
* +--------+---------+
*
- * In all but one case there is only one request for each connection made
- * to this server so we can safely close the socket after sending the
- * reply. The exception is ALIVE_REQ where we keep the connection
- * open without sending any data. When we receive a "close" this is
- * an indication that the Erlang node was terminated. The termination
- * may have been "normal" or caused by a crash. The operating system
- * ensure that the connection is closed either way.
- *
- * Reading is done non-blocking, i.e. we call a "read" only if we are
- * told by the "select" function that there are data to read.
- *
- * Two databases are used: One node database where the registered names
- * of the nodes are stored, and one connection database where the state
- * of sockets and the data buffers is stored.
- *
- * Incomplete packets are thrown away after a timout. The Erlang node
- * doing the request is responsible for completing in it in a reasonable time.
- *
- * Note that if the server gets busy it may not have time to
- * process all requests for connection. The "accept()" function
- * will on most operating systems silently refuse to accept more
- * than 5 outstanding requests. It is the client's responsibility
- * to retry the request a number of times with random time interval.
- * The "-debug" flag will insert a delay so you can test this
- * behaviour.
- *
- * FIXME: In this code we assume that the packets we send on each
- * socket is so small that a "write()" never block
- *
- * FIXME: We never restarts a read or write that was terminated
- * by an interrupt. Do we need to?
- *
*/
/* We use separate data structures for node names and connections
@@ -98,7 +68,6 @@ static int conn_open(EpmdVars*,int);
static int conn_close_fd(EpmdVars*,int);
static void node_init(EpmdVars*);
-static Node *node_reg(EpmdVars*,char*,int,int);
static Node *node_reg2(EpmdVars*,char*, int, int, unsigned char, unsigned char, int, int, int, char*);
static int node_unreg(EpmdVars*,char*);
static int node_unreg_sock(EpmdVars*,int);
@@ -303,11 +272,9 @@ static void do_read(EpmdVars *g,Connection *s)
s->fd,val);
dbg_print_buf(g,s->buf,val);
- /* FIXME: Shouldn't be needed to close down.... */
node_unreg_sock(g,s->fd);
epmd_conn_close(g,s);
}
- /* FIXME: We always close, probably the right thing to do */
return;
}
@@ -405,6 +372,8 @@ static int do_accept(EpmdVars *g,int listensock)
return conn_open(g,msgsock);
}
+/* buf is actually one byte larger than bsize,
+ giving place for null termination */
static void do_request(g, fd, s, buf, bsize)
EpmdVars *g;
int fd;
@@ -415,117 +384,23 @@ static void do_request(g, fd, s, buf, bsize)
char wbuf[OUTBUF_SIZE]; /* Buffer for writing */
int i;
- /*
- * Terminate packet as a C string. Needed for requests received from Erlang
- * nodes with lower version than R3A.
- */
-
- buf[bsize] = '\0';
+ buf[bsize] = '\0'; /* Needed for strcmp in PORT2 and STOP requests
+ buf is always large enough */
switch (*buf)
{
- case EPMD_ALIVE_REQ:
- dbg_printf(g,1,"** got ALIVE_REQ");
-
- /* The packet has the format "axxyyyyyy" where xx is port, given
- in network byte order, and yyyyyy is symname, possibly null
- terminated. */
-
- if (buf[bsize - 1] == '\000') /* Skip null termination */
- bsize--;
-
- if (bsize <= 3)
- {
- dbg_printf(g,0,"packet to small for request ALIVE_REQ (%d)", bsize);
- return;
- }
-
- for (i = 3; i < bsize; i++)
- if (buf[i] == '\000')
- {
- dbg_printf(g,0,"node name contains ascii 0 in ALIVE_REQ");
- return;
- }
-
- {
- Node *node;
- int eport;
- char *name = &buf[3]; /* points to node name */
-
- eport = get_int16(&buf[1]);
-
- if ((node = node_reg(g, name, fd, eport)) == NULL)
- return;
-
- wbuf[0] = EPMD_ALIVE_OK_RESP;
- put_int16(node->creation, wbuf+1);
-
- if (g->delay_write) /* Test of busy server */
- sleep(g->delay_write);
-
- if (reply(g, fd, wbuf, 3) != 3)
- {
- dbg_tty_printf(g,1,"failed to send ALIVE_OK_RESP for \"%s\"",name);
- return;
- }
-
- dbg_tty_printf(g,1,"** sent ALIVE_OK_RESP for \"%s\"",name);
- s->keep = EPMD_TRUE; /* Don't close on inactivity */
- }
- break;
-
- case EPMD_PORT_REQ:
- dbg_printf(g,1,"** got PORT_REQ");
-
- if (buf[bsize - 1] == '\000') /* Skip null termination */
- bsize--;
-
- if (bsize <= 1)
- {
- dbg_printf(g,0,"packet to small for request PORT_REQ (%d)", bsize);
- return;
- }
-
- for (i = 1; i < bsize; i++)
- if (buf[i] == '\000')
- {
- dbg_printf(g,0,"node name contains ascii 0 in PORT_REQ");
- return;
- }
-
- {
- char *name = &buf[1]; /* Points to node name */
- Node *node;
-
- for (node = g->nodes.reg; node; node = node->next)
- {
- if (strcmp(node->symname, name) == 0)
- {
- put_int16(node->port,wbuf);
- if (reply(g, fd, wbuf, 2) != 2)
- {
- dbg_tty_printf(g,1,"failed to send PORT_RESP for %s: %d",
- name,node->port);
- return;
- }
- dbg_tty_printf(g,1,"** sent PORT_RESP for %s: %d",
- name,node->port);
- return;
- }
- }
- dbg_tty_printf(g,1,"Closed on PORT_REQ for %s",name);
- }
- /* FIXME: How about an answer if no port? Is a close enough? */
- break;
-
case EPMD_ALIVE2_REQ:
dbg_printf(g,1,"** got ALIVE2_REQ");
+ if (!s->local_peer) {
+ dbg_printf(g,0,"ALIVE2_REQ from non local address");
+ return;
+ }
/* The packet has the format "axxyyyyyy" where xx is port, given
in network byte order, and yyyyyy is symname, possibly null
terminated. */
- if (bsize <= 13)
+ if (bsize <= 13) /* at least one character for the node name */
{
dbg_printf(g,0,"packet to small for request ALIVE2_REQ (%d)",bsize);
return;
@@ -548,7 +423,17 @@ static void do_request(g, fd, s, buf, bsize)
highvsn = get_int16(&buf[5]);
lowvsn = get_int16(&buf[7]);
namelen = get_int16(&buf[9]);
+ if (namelen + 13 > bsize) {
+ dbg_printf(g,0,"Node name size error in ALIVE2_REQ");
+ return;
+ }
extralen = get_int16(&buf[11+namelen]);
+
+ if (extralen + namelen + 13 > bsize) {
+ dbg_printf(g,0,"Extra info size error in ALIVE2_REQ");
+ return;
+ }
+
for (i = 11 ; i < 11 + namelen; i ++)
if (buf[i] == '\000') {
dbg_printf(g,0,"node name contains ascii 0 in ALIVE2_REQ");
@@ -679,6 +564,10 @@ static void do_request(g, fd, s, buf, bsize)
case EPMD_DUMP_REQ:
dbg_printf(g,1,"** got DUMP_REQ");
+ if (!s->local_peer) {
+ dbg_printf(g,0,"DUMP_REQ from non local address");
+ return;
+ }
{
Node *node;
@@ -728,7 +617,19 @@ static void do_request(g, fd, s, buf, bsize)
break;
case EPMD_KILL_REQ:
+ if (!s->local_peer) {
+ dbg_printf(g,0,"KILL_REQ from non local address");
+ return;
+ }
dbg_printf(g,1,"** got KILL_REQ");
+
+ if (!g->brutal_kill && (g->nodes.reg != NULL)) {
+ dbg_printf(g,0,"Disallowed KILL_REQ, live nodes");
+ if (reply(g, fd,"NO",2) != 2)
+ dbg_printf(g,0,"failed to send reply to KILL_REQ");
+ return;
+ }
+
if (reply(g, fd,"OK",2) != 2)
dbg_printf(g,0,"failed to send reply to KILL_REQ");
dbg_tty_printf(g,1,"epmd killed");
@@ -738,6 +639,15 @@ static void do_request(g, fd, s, buf, bsize)
case EPMD_STOP_REQ:
dbg_printf(g,1,"** got STOP_REQ");
+ if (!s->local_peer) {
+ dbg_printf(g,0,"STOP_REQ from non local address");
+ return;
+ }
+ if (!g->brutal_kill) {
+ dbg_printf(g,0,"Disallowed STOP_REQ, no relaxed_command_check");
+ return;
+ }
+
if (bsize <= 1 )
{
dbg_printf(g,0,"packet too small for request STOP_REQ (%d)",bsize);
@@ -825,6 +735,14 @@ static int conn_open(EpmdVars *g,int fd)
for (i = 0; i < g->max_conn; i++) {
if (g->conn[i].open == EPMD_FALSE) {
+ struct sockaddr_in si;
+#ifdef HAVE_SOCKLEN_T
+ socklen_t st;
+#else
+ int st;
+#endif
+ st = sizeof(si);
+
g->active_conn++;
s = &g->conn[i];
@@ -834,6 +752,20 @@ static int conn_open(EpmdVars *g,int fd)
s->fd = fd;
s->open = EPMD_TRUE;
s->keep = EPMD_FALSE;
+
+ /* Determine if connection is from localhost */
+ if (getpeername(s->fd,(struct sockaddr*) &si,&st) ||
+ st < sizeof(si)) {
+ /* Failure to get peername is regarder as non local host */
+ s->local_peer = EPMD_FALSE;
+ } else {
+ s->local_peer =
+ ((((unsigned) ntohl(si.sin_addr.s_addr)) & 0xFF000000U) ==
+ 0x7F000000U); /* Only 127.x.x.x allowed, no false positives */
+ }
+ dbg_tty_printf(g,2,(s->local_peer) ? "Local peer connected" :
+ "Non-local peer connected");
+
s->want = 0; /* Currently unknown */
s->got = 0;
s->mod_time = current_time(g); /* Note activity */
@@ -990,11 +922,6 @@ static int node_unreg_sock(EpmdVars *g,int fd)
* Perhaps use the oldest or something.
*/
-static Node *node_reg(EpmdVars *g,char *name,int fd, int port)
-{
- return node_reg2(g, name, fd, port, 0, 0, 0, 0, 0, NULL);
-}
-
static Node *node_reg2(EpmdVars *g,
char* name,
int fd,
@@ -1020,6 +947,11 @@ static Node *node_reg2(EpmdVars *g,
dbg_printf(g,0,"node name is too long (%d) %s", strlen(name), name);
return NULL;
}
+ if (extralen > MAXSYMLEN)
+ {
+ dbg_printf(g,0,"extra data is too long (%d) %s", strlen(name), name);
+ return NULL;
+ }
/* Fail if it is already registered */
diff --git a/erts/epmd/test/epmd_SUITE.erl b/erts/epmd/test/epmd_SUITE.erl
index 91e09faf75..da69412e12 100644
--- a/erts/epmd/test/epmd_SUITE.erl
+++ b/erts/epmd/test/epmd_SUITE.erl
@@ -63,7 +63,13 @@
alive_req_too_large/1,
returns_valid_empty_extra/1,
- returns_valid_populated_extra_with_nulls/1
+ returns_valid_populated_extra_with_nulls/1,
+ buffer_overrun/1,
+ buffer_overrun_1/1,
+ buffer_overrun_2/1,
+ no_nonlocal_register/1,
+ no_nonlocal_kill/1,
+ no_live_killing/1
]).
@@ -82,11 +88,8 @@
-define(REG_REPEAT_LIM,1000).
% Message codes in epmd protocol
--define(EPMD_ALIVE_REQ, $a).
-define(EPMD_ALIVE2_REQ, $x).
--define(EPMD_ALIVE_OK_RESP, $Y).
-define(EPMD_ALIVE2_RESP, $y).
--define(EPMD_PORT_REQ, $p).
-define(EPMD_PORT_PLEASE2_REQ, $z).
-define(EPMD_PORT2_RESP, $w).
-define(EPMD_NAMES_REQ, $n).
@@ -124,7 +127,15 @@ all(suite) ->
alive_req_too_large,
returns_valid_empty_extra,
- returns_valid_populated_extra_with_nulls
+ returns_valid_populated_extra_with_nulls,
+
+ buffer_overrun,
+ %buffer_overrun_1,
+ %buffer_overrun_2,
+
+ no_nonlocal_register,
+ no_nonlocal_kill,
+ no_live_killing
].
%%
@@ -132,7 +143,7 @@ all(suite) ->
%%
init_per_testcase(_Func, Config) ->
- Dog = test_server:timetrap(?SHORT_TEST_TIMEOUT),
+ Dog = test_server:timetrap(?MEDIUM_TEST_TIMEOUT),
cleanup(),
[{watchdog, Dog} | Config].
@@ -148,7 +159,7 @@ register_name(doc) ->
["Register a name"];
register_name(suite) ->
[];
-register_name(Config) when list(Config) ->
+register_name(Config) when is_list(Config) ->
?line ok = epmdrun(),
?line {ok,Sock} = register_node("foobar"),
?line ok = close(Sock), % Unregister
@@ -158,7 +169,7 @@ register_names_1(doc) ->
["Register and unregister two nodes"];
register_names_1(suite) ->
[];
-register_names_1(Config) when list(Config) ->
+register_names_1(Config) when is_list(Config) ->
?line ok = epmdrun(),
?line {ok,Sock1} = register_node("foobar"),
?line {ok,Sock2} = register_node("foozap"),
@@ -170,7 +181,7 @@ register_names_2(doc) ->
["Register and unregister two nodes"];
register_names_2(suite) ->
[];
-register_names_2(Config) when list(Config) ->
+register_names_2(Config) when is_list(Config) ->
?line ok = epmdrun(),
?line {ok,Sock1} = register_node("foobar"),
?line {ok,Sock2} = register_node("foozap"),
@@ -182,7 +193,7 @@ register_duplicate_name(doc) ->
["Two nodes with the same name"];
register_duplicate_name(suite) ->
[];
-register_duplicate_name(Config) when list(Config) ->
+register_duplicate_name(Config) when is_list(Config) ->
?line ok = epmdrun(),
?line {ok,Sock} = register_node("foobar"),
?line error = register_node("foobar"),
@@ -192,22 +203,9 @@ register_duplicate_name(Config) when list(Config) ->
% Internal function to register a node name, no close, i.e. unregister
register_node(Name) ->
- register_node(Name,?DUMMY_PORT).
-
-register_node(Name, Port) ->
- case send_req([?EPMD_ALIVE_REQ, put16(Port), Name]) of
- {ok,Sock} ->
- case recv(Sock,3) of
- {ok, [?EPMD_ALIVE_OK_RESP,_D1,_D0]} ->
- {ok,Sock};
- Other ->
- test_server:format("recv on sock ~w: ~p~n",
- [Sock,Other]),
- error
- end;
- error ->
- error
- end.
+ register_node_v2(?DUMMY_PORT,$M,0,5,5,Name,"").
+register_node(Name,Port) ->
+ register_node_v2(Port,$M,0,5,5,Name,"").
register_node_v2(Port, NodeType, Prot, HVsn, LVsn, Name, Extra) ->
Req = [?EPMD_ALIVE2_REQ, put16(Port), NodeType, Prot,
@@ -254,7 +252,7 @@ parse_port2_resp(Resp) ->
hvsn=HVsn,lvsn=LVsn,
node_name=binary_to_list(NodeName),
extra=binary_to_list(Extra)}};
- Other ->
+ _Other ->
test_server:format("invalid port2 resp: ~p~n",
[Resp]),
error
@@ -266,7 +264,7 @@ name_with_null_inside(doc) ->
["Register a name with a null char in it"];
name_with_null_inside(suite) ->
[];
-name_with_null_inside(Config) when list(Config) ->
+name_with_null_inside(Config) when is_list(Config) ->
?line ok = epmdrun(),
?line error = register_node("foo\000bar"),
ok.
@@ -277,11 +275,9 @@ name_null_terminated(doc) ->
["Register a name with terminating null byte"];
name_null_terminated(suite) ->
[];
-name_null_terminated(Config) when list(Config) ->
+name_null_terminated(Config) when is_list(Config) ->
?line ok = epmdrun(),
- ?line {ok,Sock} = register_node("foobar\000"),
- ?line error = register_node("foobar"),
- ?line ok = close(Sock), % Unregister
+ ?line error = register_node("foobar\000"),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -290,7 +286,7 @@ stupid_names_req(doc) ->
["Read names from epmd in a stupid way"];
stupid_names_req(suite) ->
[];
-stupid_names_req(Config) when list(Config) ->
+stupid_names_req(Config) when is_list(Config) ->
Dog = ?config(watchdog, Config),
test_server:timetrap_cancel(Dog),
LongDog = test_server:timetrap(?MEDIUM_TEST_TIMEOUT),
@@ -394,15 +390,15 @@ get_port_nr(doc) ->
["Register a name on a port and ask about port nr"];
get_port_nr(suite) ->
[];
-get_port_nr(Config) when list(Config) ->
- port_request([?EPMD_PORT_REQ,"foo"]).
+get_port_nr(Config) when is_list(Config) ->
+ port_request([?EPMD_PORT_PLEASE2_REQ,"foo"]).
slow_get_port_nr(doc) ->
["Register with slow write and ask about port nr"];
slow_get_port_nr(suite) ->
[];
-slow_get_port_nr(Config) when list(Config) ->
- port_request([?EPMD_PORT_REQ,d,$f,d,$o,d,$o]).
+slow_get_port_nr(Config) when is_list(Config) ->
+ port_request([?EPMD_PORT_PLEASE2_REQ,d,$f,d,$o,d,$o]).
% Internal function used above
@@ -413,9 +409,18 @@ port_request(M) ->
?line {ok,RSock} = register_node("foo", Port),
?line {ok,Sock} = connect(),
?line ok = send(Sock,[size16(M),M]),
- R = put16(Port),
- ?line {ok,R} = recv(Sock, length(R)),
- ?line ok = close(RSock),
+ ?line case recv_until_sock_closes(Sock) of
+ {ok, Resp} ->
+ ?line close(RSock),
+ ?line {ok,Rec} = parse_port2_resp(Resp),
+ ?line Port = Rec#node_info.port,
+ ok;
+ Other ->
+ ?line close(RSock),
+ ?line test_server:format("recv on sock ~w: ~p~n",
+ [Sock,Other]),
+ ?line throw({error,Other})
+ end,
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -424,8 +429,8 @@ unregister_others_name_1(doc) ->
["Unregister name of other node"];
unregister_others_name_1(suite) ->
[];
-unregister_others_name_1(Config) when list(Config) ->
- ?line ok = epmdrun(),
+unregister_others_name_1(Config) when is_list(Config) ->
+ ?line ok = epmdrun("-relaxed_command_check"),
?line {ok,RSock} = register_node("foo"),
?line {ok,Sock} = connect(),
M = [?EPMD_STOP_REQ,"foo"],
@@ -441,8 +446,8 @@ unregister_others_name_2(doc) ->
["Unregister name of other node"];
unregister_others_name_2(suite) ->
[];
-unregister_others_name_2(Config) when list(Config) ->
- ?line ok = epmdrun(),
+unregister_others_name_2(Config) when is_list(Config) ->
+ ?line ok = epmdrun("-relaxed_command_check"),
?line {ok,Sock} = connect(),
M = [?EPMD_STOP_REQ,"xxx42"],
?line ok = send(Sock,[size16(M),M]),
@@ -456,7 +461,7 @@ register_overflow(doc) ->
["Register too many, clean and redo 10 times"];
register_overflow(suite) ->
[];
-register_overflow(Config) when list(Config) ->
+register_overflow(Config) when is_list(Config) ->
Dog = ?config(watchdog, Config),
test_server:timetrap_cancel(Dog),
LongDog = test_server:timetrap(?LONG_TEST_TIMEOUT),
@@ -546,7 +551,7 @@ no_data(doc) ->
["Open but send no data"];
no_data(suite) ->
[];
-no_data(Config) when list(Config) ->
+no_data(Config) when is_list(Config) ->
?line ok = epmdrun(),
?line {ok,Sock} = connect(),
sleep(?LONG_PAUSE),
@@ -559,7 +564,7 @@ one_byte(doc) ->
["Send one byte only"];
one_byte(suite) ->
[];
-one_byte(Config) when list(Config) ->
+one_byte(Config) when is_list(Config) ->
?line ok = epmdrun(),
?line {ok,Sock} = connect(),
?line ok = send(Sock,[0]),
@@ -573,7 +578,7 @@ two_bytes(doc) ->
["Send packet size only"];
two_bytes(suite) ->
[];
-two_bytes(Config) when list(Config) ->
+two_bytes(Config) when is_list(Config) ->
?line ok = epmdrun(),
?line {ok,Sock} = connect(),
?line ok = send(Sock,[put16(3)]),
@@ -587,7 +592,7 @@ partial_packet(doc) ->
["Got only part of a packet"];
partial_packet(suite) ->
[];
-partial_packet(Config) when list(Config) ->
+partial_packet(Config) when is_list(Config) ->
?line ok = epmdrun(),
?line {ok,Sock} = connect(),
?line ok = send(Sock,[put16(100),"only a few bytes"]),
@@ -601,7 +606,7 @@ zero_length(doc) ->
["Invalid zero packet size"];
zero_length(suite) ->
[];
-zero_length(Config) when list(Config) ->
+zero_length(Config) when is_list(Config) ->
?line ok = epmdrun(),
?line {ok,Sock} = connect(),
?line ok = send(Sock,[0,0,0,0,0,0,0,0,0,0]),
@@ -615,15 +620,20 @@ too_large(doc) ->
["Invalid large packet"];
too_large(suite) ->
[];
-too_large(Config) when list(Config) ->
+too_large(Config) when is_list(Config) ->
?line ok = epmdrun(),
?line {ok,Sock} = connect(),
Size = 63000,
M = lists:duplicate(Size, $z),
?line ok = send(Sock,[put16(Size),M]),
sleep(?MEDIUM_PAUSE),
- ?line closed = recv(Sock,1),
- ok.
+ % With such a large packet, even the writes can fail as the
+ % daemon closes before everything is delivered -> econnaborted
+ case recv(Sock,1) of
+ closed -> ok;
+ {error,econnaborted} -> ok;
+ Other -> exit({unexpected,Other})
+ end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -631,10 +641,11 @@ alive_req_too_small_1(doc) ->
["Try to register but not enough data"];
alive_req_too_small_1(suite) ->
[];
-alive_req_too_small_1(Config) when list(Config) ->
+alive_req_too_small_1(Config) when is_list(Config) ->
?line ok = epmdrun(),
?line {ok,Sock} = connect(),
- M = [?EPMD_ALIVE_REQ, 42],
+ M = [?EPMD_ALIVE2_REQ, put16(?DUMMY_PORT),$M,0, put16(5),
+ put16(5),put16(0)],
?line ok = send(Sock, [size16(M), M]),
sleep(?MEDIUM_PAUSE),
?line closed = recv(Sock,1),
@@ -646,10 +657,11 @@ alive_req_too_small_2(doc) ->
["Try to register but not enough data"];
alive_req_too_small_2(suite) ->
[];
-alive_req_too_small_2(Config) when list(Config) ->
+alive_req_too_small_2(Config) when is_list(Config) ->
?line ok = epmdrun(),
?line {ok,Sock} = connect(),
- M = [?EPMD_ALIVE_REQ, put16(?DUMMY_PORT)],
+ M = [?EPMD_ALIVE2_REQ, put16(?DUMMY_PORT),$M,0, put16(5),
+ put16(5)],
?line ok = send(Sock, [size16(M), M]),
sleep(?MEDIUM_PAUSE),
?line closed = recv(Sock,1),
@@ -661,7 +673,7 @@ alive_req_too_large(doc) ->
["Try to register but node name too large"];
alive_req_too_large(suite) ->
[];
-alive_req_too_large(Config) when list(Config) ->
+alive_req_too_large(Config) when is_list(Config) ->
?line ok = epmdrun(),
?line {ok,Sock} = connect(),
L = [
@@ -678,10 +690,12 @@ alive_req_too_large(Config) when list(Config) ->
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
],
- M = [?EPMD_ALIVE_REQ, put16(?DUMMY_PORT), L],
+ S = length(lists:flatten(L)),
+ M = [?EPMD_ALIVE2_REQ, put16(?DUMMY_PORT),$M,0, put16(5),
+ put16(5), put16(S),L,put16(0)],
?line ok = send(Sock, [size16(M), M]),
sleep(?MEDIUM_PAUSE),
- ?line closed = recv(Sock,1),
+ ?line {ok,[?EPMD_ALIVE2_RESP,1]} = recv(Sock,2),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -690,7 +704,7 @@ returns_valid_empty_extra(doc) ->
["Check that an empty extra is prefixed by a two byte length"];
returns_valid_empty_extra(suite) ->
[];
-returns_valid_empty_extra(Config) when list(Config) ->
+returns_valid_empty_extra(Config) when is_list(Config) ->
?line ok = epmdrun(),
?line {ok,Sock} = register_node_v2(4711, 72, 0, 5, 5, "foo", []),
?line {ok,#node_info{extra=[]}} = port_please_v2("foo"),
@@ -703,7 +717,7 @@ returns_valid_populated_extra_with_nulls(doc) ->
["Check a populated extra with embedded null characters"];
returns_valid_populated_extra_with_nulls(suite) ->
[];
-returns_valid_populated_extra_with_nulls(Config) when list(Config) ->
+returns_valid_populated_extra_with_nulls(Config) when is_list(Config) ->
?line ok = epmdrun(),
?line {ok,Sock} = register_node_v2(4711, 72, 0, 5, 5, "foo", "ABC\000\000"),
?line {ok,#node_info{extra="ABC\000\000"}} = port_please_v2("foo"),
@@ -711,6 +725,167 @@ returns_valid_populated_extra_with_nulls(Config) when list(Config) ->
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+buffer_overrun(suite) ->
+ [buffer_overrun_1,buffer_overrun_2].
+
+buffer_overrun_1(suite) ->
+ [];
+buffer_overrun_1(doc) ->
+ ["Test security vulnerability in fake extra lengths in alive2_req"];
+buffer_overrun_1(Config) when is_list(Config) ->
+ ?line ok = epmdrun(),
+ ?line true = alltrue([hostile(N) || N <- lists:seq(1,10000)]),
+ ok.
+buffer_overrun_2(suite) ->
+ [];
+buffer_overrun_2(doc) ->
+ ["Test security vulnerability in fake extra lengths in alive2_req"];
+buffer_overrun_2(Config) when is_list(Config) ->
+ ?line ok = epmdrun(),
+ ?line [false | Rest] = [hostile2(N) || N <- lists:seq(255,10000)],
+ ?line true = alltrue(Rest),
+ ok.
+hostile(N) ->
+ try
+ Bin= <<$x:8,4747:16,$M:8,0:8,5:16,5:16,5:16,"gurka",N:16>>,
+ S = size(Bin),
+ {ok,E}=connect_sturdy(),
+ gen_tcp:send(E,[<<S:16>>,Bin]),
+ closed = recv(E,1),
+ gen_tcp:close(E),
+ true
+ catch
+ _:_ ->
+ false
+ end.
+hostile2(N) ->
+ try
+ B2 = list_to_binary(lists:duplicate(N,255)),
+ Bin= <<$x:8,4747:16,$M:8,0:8,5:16,5:16,5:16,"gurka",N:16,B2/binary>>,
+ S = size(Bin),
+ {ok,E}=connect_sturdy(),
+ gen_tcp:send(E,[<<S:16>>,Bin]),
+ Z = recv(E,2),
+ gen_tcp:close(E),
+ (Z =:= closed) or (Z =:= {ok, [$y,1]})
+ catch
+ _A:_B ->
+ false
+ end.
+
+alltrue([]) ->
+ true;
+alltrue([true|T]) ->
+ alltrue(T);
+alltrue([_|_]) ->
+ false.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+no_nonlocal_register(suite) ->
+ [];
+no_nonlocal_register(doc) ->
+ ["Ensure that we cannot register throug a nonlocal connection"];
+no_nonlocal_register(Config) when is_list(Config) ->
+ ?line ok = epmdrun(),
+ ?line {ok,Ifs} = inet:getiflist(),
+ ?line Addr0 = [ inet:ifget(I, [addr]) || I <- Ifs ],
+ ?line Addr1 = [ A || {ok,[{addr,A}]} <- Addr0],
+ ?line Addr = lists:filter(fun({127,_,_,_}) ->
+ false;
+ (_) ->
+ true
+ end,Addr1),
+ %% Now we should have all non loopback interface addresses,
+ %% none should accept a alive2 registration.
+ ?line Res = lists:map(fun(Ad={A1,A2,A3,A4}) ->
+ try
+ Name = "gurka_"++
+ integer_to_list(A1)++"_"++
+ integer_to_list(A2)++"_"++
+ integer_to_list(A3)++"_"++
+ integer_to_list(A4),
+ Bname = list_to_binary(Name),
+ NameS = byte_size(Bname),
+ ?line Bin= <<$x:8,4747:16,$M:8,0:8,5:16,
+ 5:16,NameS:16,Bname/binary,
+ 0:16>>,
+ ?line S = size(Bin),
+ {ok, E} = connect(Ad),
+ gen_tcp:send(E,[<<S:16>>,Bin]),
+ closed = recv(E,1),
+ gen_tcp:close(E),
+ true
+ catch
+ _:_ ->
+ false
+ end
+ end, Addr),
+ erlang:display(Res),
+ ?line true = alltrue(Res),
+ ok.
+
+no_nonlocal_kill(suite) ->
+ [];
+no_nonlocal_kill(doc) ->
+ ["Ensure that we cannot kill through nonlocal connection"];
+no_nonlocal_kill(Config) when is_list(Config) ->
+ ?line ok = epmdrun(),
+ ?line {ok,Ifs} = inet:getiflist(),
+ ?line Addr0 = [ inet:ifget(I, [addr]) || I <- Ifs ],
+ ?line Addr1 = [ A || {ok,[{addr,A}]} <- Addr0],
+ ?line Addr = lists:filter(fun({127,_,_,_}) ->
+ false;
+ (_) ->
+ true
+ end,Addr1),
+ %% Now we should have all non loopback interface addresses,
+ %% none should accept a alive2 registration.
+ ?line Res = lists:map(fun(Ad) ->
+ try
+ {ok, E} = connect(Ad),
+ M = [?EPMD_KILL_REQ],
+ send(E, [size16(M), M]),
+ closed = recv(E,2),
+ gen_tcp:close(E),
+ sleep(?MEDIUM_PAUSE),
+ {ok, E2} = connect(Ad),
+ gen_tcp:close(E2),
+ true
+ catch
+ _:_ ->
+ false
+ end
+ end, Addr),
+ erlang:display(Res),
+ ?line true = alltrue(Res),
+ ok.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+no_live_killing(doc) ->
+ ["Dont allow killing with live nodes or any unregistering w/o -relaxed_command_check"];
+no_live_killing(suite) ->
+ [];
+no_live_killing(Config) when is_list(Config) ->
+ ?line ok = epmdrun(),
+ ?line {ok,RSock} = register_node("foo"),
+ ?line {ok,Sock} = connect(),
+ ?line M = [?EPMD_KILL_REQ],
+ ?line ok = send(Sock,[size16(M),M]),
+ ?line {ok,"NO"} = recv(Sock,2),
+ ?line close(Sock),
+ ?line {ok,Sock2} = connect(),
+ ?line M2 = [?EPMD_STOP_REQ,"foo"],
+ ?line ok = send(Sock2,[size16(M2),M2]),
+ ?line closed = recv(Sock2,1),
+ ?line close(Sock2),
+ ?line close(RSock),
+ ?line sleep(?MEDIUM_PAUSE),
+ ?line {ok,Sock3} = connect(),
+ ?line M3 = [?EPMD_KILL_REQ],
+ ?line ok = send(Sock3,[size16(M3),M3]),
+ ?line {ok,"OK"} = recv(Sock3,2),
+ ?line close(Sock3),
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Terminate all tests with killing epmd.
cleanup() ->
@@ -731,16 +906,24 @@ cleanup() ->
% Normal debug start of epmd
epmdrun() ->
+ epmdrun([]).
+epmdrun(Args) ->
case os:find_executable(epmd) of
false ->
{error, {could_not_find_epmd_in_path}};
Path ->
- epmdrun(Path)
+ epmdrun(Path,Args)
end.
-epmdrun(Epmd) ->
+epmdrun(Epmd,Args0) ->
%% test_server:format("epmdrun() => Epmd = ~p",[Epmd]),
- osrun(Epmd ++ " " ?EPMDARGS " -port " ++ integer_to_list(?PORT)).
+ Args = case Args0 of
+ [] ->
+ [];
+ O ->
+ " "++O
+ end,
+ osrun(Epmd ++ Args ++ " " ?EPMDARGS " -port " ++ integer_to_list(?PORT)).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -753,20 +936,27 @@ osrun(Cmd) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Wrappers of TCP functions
-% These two functions is the interface for connect.
+% These functions is the interface for connect.
% Passive mode is the default
connect() ->
- connect(?PORT, passive).
+ connect("localhost",?PORT, passive).
+
+connect(Addr) ->
+ connect(Addr,?PORT, passive).
connect_active() ->
- connect(?PORT, active).
+ connect("localhost",?PORT, active).
+%% Retry after 15 seconds, to avoid TIME_WAIT socket exhaust.
+connect_sturdy() ->
+ connect("localhost",?PORT, passive, 15000, 3).
% Try a few times before giving up
-
-connect(Port, Mode) ->
- case connect_repeat(?CONN_RETRY, Port, Mode) of
+connect(Addr, Port, Mode) ->
+ connect(Addr, Port, Mode, ?CONN_SLEEP, ?CONN_RETRY).
+connect(Addr, Port, Mode, Sleep, Retry) ->
+ case connect_repeat(Addr, Retry, Port, Mode, Sleep) of
{ok,Sock} ->
{ok,Sock};
{error,timeout} ->
@@ -783,25 +973,25 @@ connect(Port, Mode) ->
% Try a few times before giving up. Pause a small time between
% each try.
-connect_repeat(1, Port, Mode) ->
- connect_mode(Port, Mode);
-connect_repeat(Retry, Port, Mode) ->
- case connect_mode(Port, Mode) of
+connect_repeat(Addr, 1, Port, Mode, _Sleep) ->
+ connect_mode(Addr,Port, Mode);
+connect_repeat(Addr,Retry, Port, Mode, Sleep) ->
+ case connect_mode(Addr,Port, Mode) of
{ok,Sock} ->
{ok,Sock};
{error,Reason} ->
test_server:format("connect: error: ~w~n",[Reason]),
- timer:sleep(?CONN_SLEEP),
- connect_repeat(Retry - 1, Port, Mode);
+ timer:sleep(Sleep),
+ connect_repeat(Addr, Retry - 1, Port, Mode, Sleep);
Any ->
test_server:format("connect: unknown message: ~w~n",[Any]),
exit(1)
end.
-connect_mode(Port, active) ->
- gen_tcp:connect("localhost", Port, [{packet, 0}], ?CONN_TIMEOUT);
-connect_mode(Port, passive) ->
- gen_tcp:connect("localhost", Port, [{packet, 0}, {active, false}],
+connect_mode(Addr,Port, active) ->
+ gen_tcp:connect(Addr, Port, [{packet, 0}], ?CONN_TIMEOUT);
+connect_mode(Addr, Port, passive) ->
+ gen_tcp:connect(Addr, Port, [{packet, 0}, {active, false}],
?CONN_TIMEOUT).
@@ -858,9 +1048,9 @@ send(Sock, SendSpec) ->
send([], RevBytes, _Sock) ->
{ok,RevBytes};
-send([Byte | Spec], RevBytes, Sock) when integer(Byte) ->
+send([Byte | Spec], RevBytes, Sock) when is_integer(Byte) ->
send(Spec, [Byte | RevBytes], Sock);
-send([List | Spec], RevBytes, Sock) when list(List) ->
+send([List | Spec], RevBytes, Sock) when is_list(List) ->
case send(List, RevBytes, Sock) of
{ok,Left} ->
send(Spec, Left, Sock);
diff --git a/erts/etc/common/Makefile.in b/erts/etc/common/Makefile.in
index 96655662b8..e866511153 100644
--- a/erts/etc/common/Makefile.in
+++ b/erts/etc/common/Makefile.in
@@ -327,31 +327,31 @@ $(OBJDIR)/$(ERLEXEC).o: $(ERLEXECDIR)/$(ERLEXEC).c
$(CC) -I$(EMUDIR) $(CFLAGS) -o $@ -c $(ERLEXECDIR)/$(ERLEXEC).c
endif
$(BINDIR)/erlc@EXEEXT@: $(OBJDIR)/erlc.o
- $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/erlc.o -L$(OBJDIR) $(LIBS)
+ $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/erlc.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS)
$(OBJDIR)/erlc.o: erlc.c
$(CC) $(CFLAGS) -o $@ -c erlc.c
$(BINDIR)/dialyzer@EXEEXT@: $(OBJDIR)/dialyzer.o
- $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/dialyzer.o -L$(OBJDIR) $(LIBS)
+ $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/dialyzer.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS)
$(OBJDIR)/dialyzer.o: dialyzer.c
$(CC) $(CFLAGS) -o $@ -c dialyzer.c
$(BINDIR)/typer@EXEEXT@: $(OBJDIR)/typer.o
- $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/typer.o -L$(OBJDIR) $(LIBS)
+ $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/typer.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS)
$(OBJDIR)/typer.o: typer.c
$(CC) $(CFLAGS) -o $@ -c typer.c
$(BINDIR)/escript@EXEEXT@: $(OBJDIR)/escript.o
- $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/escript.o -L$(OBJDIR) $(LIBS)
+ $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/escript.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS)
$(OBJDIR)/escript.o: escript.c
$(CC) $(CFLAGS) -o $@ -c escript.c
$(BINDIR)/run_test@EXEEXT@: $(OBJDIR)/run_test.o
- $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/run_test.o -L$(OBJDIR) $(LIBS)
+ $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/run_test.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS)
$(OBJDIR)/run_test.o: run_test.c
$(CC) $(CFLAGS) -o $@ -c run_test.c
diff --git a/erts/etc/common/dialyzer.c b/erts/etc/common/dialyzer.c
index 4b4c1124f1..4453e63f1c 100644
--- a/erts/etc/common/dialyzer.c
+++ b/erts/etc/common/dialyzer.c
@@ -147,6 +147,9 @@ main(int argc, char** argv)
env = get_env("DIALYZER_EMULATOR");
emulator = env ? env : get_default_emulator(argv[0]);
+ if (strlen(emulator) >= MAXPATHLEN)
+ error("Value of environment variable DIALYZER_EMULATOR is too large");
+
/*
* Allocate the argv vector to be used for arguments to Erlang.
* Arrange for starting to pushing information in the middle of
@@ -228,7 +231,7 @@ main(int argc, char** argv)
static void
push_words(char* src)
{
- char sbuf[1024];
+ char sbuf[MAXPATHLEN];
char* dst;
dst = sbuf;
@@ -360,7 +363,7 @@ error(char* format, ...)
va_list ap;
va_start(ap, format);
- vsprintf(sbuf, format, ap);
+ erts_vsnprintf(sbuf, sizeof(sbuf), format, ap);
va_end(ap);
fprintf(stderr, "dialyzer: %s\n", sbuf);
exit(1);
@@ -389,6 +392,9 @@ get_default_emulator(char* progname)
char sbuf[MAXPATHLEN];
char* s;
+ if (strlen(progname) >= sizeof(sbuf))
+ return ERL_NAME;
+
strcpy(sbuf, progname);
for (s = sbuf+strlen(sbuf); s >= sbuf; s--) {
if (IS_DIRSEP(*s)) {
diff --git a/erts/etc/common/erlc.c b/erts/etc/common/erlc.c
index 09aca19e6c..cd137435d1 100644
--- a/erts/etc/common/erlc.c
+++ b/erts/etc/common/erlc.c
@@ -148,10 +148,6 @@ int
main(int argc, char** argv)
{
char cwd[MAXPATHLEN]; /* Current working directory. */
- char** rpc_eargv; /* Pointer to the beginning of arguments
- * if calling a running Erlang system
- * via erl_rpc().
- */
int eargv_size;
int eargc_base; /* How many arguments in the base of eargv. */
char* emulator;
@@ -160,6 +156,9 @@ main(int argc, char** argv)
env = get_env("ERLC_EMULATOR");
emulator = env ? env : get_default_emulator(argv[0]);
+ if (strlen(emulator) >= MAXPATHLEN)
+ error("Value of environment variable ERLC_EMULATOR is too large");
+
/*
* Allocate the argv vector to be used for arguments to Erlang.
* Arrange for starting to pushing information in the middle of
@@ -170,7 +169,7 @@ main(int argc, char** argv)
* base of the eargv vector, and move it up later.
*/
- eargv_size = argc*4+100;
+ eargv_size = argc*6+100;
eargv_base = (char **) emalloc(eargv_size*sizeof(char*));
eargv = eargv_base;
eargc = 0;
@@ -189,7 +188,6 @@ main(int argc, char** argv)
PUSH2("-mode", "minimal");
PUSH2("-boot", "start_clean");
PUSH3("-s", "erl_compile", "compile_cmdline");
- rpc_eargv = eargv+eargc;
/*
* Push standard arguments to Erlang.
@@ -419,7 +417,7 @@ process_opt(int* pArgc, char*** pArgv, int offset)
static void
push_words(char* src)
{
- char sbuf[1024];
+ char sbuf[MAXPATHLEN];
char* dst;
dst = sbuf;
@@ -595,7 +593,7 @@ error(char* format, ...)
va_list ap;
va_start(ap, format);
- vsprintf(sbuf, format, ap);
+ erts_vsnprintf(sbuf, sizeof(sbuf), format, ap);
va_end(ap);
fprintf(stderr, "erlc: %s\n", sbuf);
exit(1);
@@ -624,6 +622,9 @@ get_default_emulator(char* progname)
char sbuf[MAXPATHLEN];
char* s;
+ if (strlen(progname) >= sizeof(sbuf))
+ return ERL_NAME;
+
strcpy(sbuf, progname);
for (s = sbuf+strlen(sbuf); s >= sbuf; s--) {
if (IS_DIRSEP(*s)) {
diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c
index 76ce0a7e3c..60b3af7db7 100644
--- a/erts/etc/common/erlexec.c
+++ b/erts/etc/common/erlexec.c
@@ -120,6 +120,7 @@ static char *plusM_other_switches[] = {
static char *pluss_val_switches[] = {
"bt",
"ct",
+ "wt",
"ss",
NULL
};
@@ -137,6 +138,12 @@ static char *plusr_val_switches[] = {
NULL
};
+/* +z arguments with values */
+static char *plusz_val_switches[] = {
+ "dbbl",
+ NULL
+};
+
/*
* Define sleep(seconds) in terms of Sleep() on Windows.
@@ -308,7 +315,7 @@ free_env_val(char *value)
}
/*
- * Add the arcitecture suffix to the program name if needed,
+ * Add the architecture suffix to the program name if needed,
* except on Windows, where we insert it just before ".DLL".
*/
static char*
@@ -559,7 +566,7 @@ int main(int argc, char **argv)
usage("+MYm");
}
emu = add_extra_suffixes(emu, emu_type);
- sprintf(tmpStr, "%s" DIRSEP "%s" BINARY_EXT, bindir, emu);
+ erts_snprintf(tmpStr, sizeof(tmpStr), "%s" DIRSEP "%s" BINARY_EXT, bindir, emu);
emu = strsave(tmpStr);
add_Eargs(emu); /* Will be argv[0] -- necessary! */
@@ -570,12 +577,12 @@ int main(int argc, char **argv)
s = get_env("PATH");
if (!s) {
- sprintf(tmpStr, "%s" PATHSEP "%s" DIRSEP "bin", bindir, rootdir);
+ erts_snprintf(tmpStr, sizeof(tmpStr), "%s" PATHSEP "%s" DIRSEP "bin", bindir, rootdir);
} else if (strstr(s, bindir) == NULL) {
- sprintf(tmpStr, "%s" PATHSEP "%s" DIRSEP "bin" PATHSEP "%s", bindir,
+ erts_snprintf(tmpStr, sizeof(tmpStr), "%s" PATHSEP "%s" DIRSEP "bin" PATHSEP "%s", bindir,
rootdir, s);
} else {
- sprintf(tmpStr, "%s", s);
+ erts_snprintf(tmpStr, sizeof(tmpStr), "%s", s);
}
free_env_val(s);
set_env("PATH", tmpStr);
@@ -713,7 +720,7 @@ int main(int argc, char **argv)
error("-man not supported on Windows");
#else
argv[i] = "man";
- sprintf(tmpStr, "%s/man", rootdir);
+ erts_snprintf(tmpStr, sizeof(tmpStr), "%s/man", rootdir);
set_env("MANPATH", tmpStr);
execvp("man", argv+i);
error("Could not execute the 'man' command.");
@@ -908,6 +915,20 @@ int main(int argc, char **argv)
i++;
}
break;
+ case 'z':
+ if (!is_one_of_strings(&argv[i][2], plusz_val_switches)) {
+ goto the_default;
+ } else {
+ if (i+1 >= argc
+ || argv[i+1][0] == '-'
+ || argv[i+1][0] == '+')
+ usage(argv[i]);
+ argv[i][0] = '-';
+ add_Eargs(argv[i]);
+ add_Eargs(argv[i+1]);
+ i++;
+ }
+ break;
default:
the_default:
argv[i][0] = '-'; /* Change +option to -option. */
@@ -1095,7 +1116,7 @@ usage_aux(void)
"[+l] [+M<SUBSWITCH> <ARGUMENT>] [+P MAX_PROCS] [+R COMPAT_REL] "
"[+r] [+rg READER_GROUPS_LIMIT] [+s SCHEDULER_OPTION] "
"[+S NO_SCHEDULERS:NO_SCHEDULERS_ONLINE] [+T LEVEL] [+V] [+v] "
- "[+W<i|w>] [args ...]\n");
+ "[+W<i|w>] [+z MISC_OPTION] [args ...]\n");
exit(1);
}
@@ -1144,10 +1165,10 @@ start_epmd(char *epmd)
if (!epmd) {
epmd = epmd_cmd;
#ifdef __WIN32__
- sprintf(epmd_cmd, "%s" DIRSEP "epmd", bindir);
+ erts_snprintf(epmd_cmd, sizeof(epmd_cmd), "%s" DIRSEP "epmd", bindir);
arg1 = "-daemon";
#else
- sprintf(epmd_cmd, "%s" DIRSEP "epmd -daemon", bindir);
+ erts_snprintf(epmd_cmd, sizeof(epmd_cmd), "%s" DIRSEP "epmd -daemon", bindir);
#endif
}
#ifdef __WIN32__
@@ -1223,7 +1244,7 @@ void error(char* format, ...)
va_list ap;
va_start(ap, format);
- vsprintf(sbuf, format, ap);
+ erts_vsnprintf(sbuf, sizeof(sbuf), format, ap);
va_end(ap);
fprintf(stderr, "erlexec: %s\n", sbuf);
exit(1);
@@ -1303,14 +1324,14 @@ static void get_start_erl_data(char *file)
if (env)
reldir = strsave(env);
else {
- sprintf(tmpbuffer, "%s/releases", rootdir);
+ erts_snprintf(tmpbuffer, sizeof(tmpbuffer), "%s/releases", rootdir);
reldir = strsave(tmpbuffer);
}
free_env_val(env);
if (file == NULL)
- sprintf(start_erl_data, "%s/start_erl.data", reldir);
+ erts_snprintf(start_erl_data, sizeof(start_erl_data), "%s/start_erl.data", reldir);
else
- sprintf(start_erl_data, "%s", file);
+ erts_snprintf(start_erl_data, sizeof(start_erl_data), "%s", file);
fp = _open(start_erl_data, _O_RDONLY );
if( fp == -1 )
error( "open failed on %s",start_erl_data );
@@ -1340,16 +1361,16 @@ static void get_start_erl_data(char *file)
}
bindir = emalloc(512);
- sprintf(bindir,"%s/erts-%s/bin",rootdir,tmpbuffer);
+ erts_snprintf(bindir,512,"%s/erts-%s/bin",rootdir,tmpbuffer);
/* BINDIR=$ROOTDIR/erts-$ERTS_VSN/bin */
tprogname = progname;
progname = emalloc(strlen(tprogname) + 20);
- sprintf(progname,"%s -start_erl",tprogname);
+ erts_snprintf(progname,strlen(tprogname) + 20,"%s -start_erl",tprogname);
boot_script = emalloc(512);
config_script = emalloc(512);
- sprintf(boot_script, "%s/%s/start", reldir, otpstring);
- sprintf(config_script, "%s/%s/sys", reldir, otpstring);
+ erts_snprintf(boot_script, 512, "%s/%s/start", reldir, otpstring);
+ erts_snprintf(config_script, 512, "%s/%s/sys", reldir, otpstring);
}
@@ -1357,7 +1378,7 @@ static void get_start_erl_data(char *file)
static char *replace_filename(char *path, char *new_base)
{
int plen = strlen(path);
- char *res = malloc((plen+strlen(new_base)+1)*sizeof(char));
+ char *res = emalloc((plen+strlen(new_base)+1)*sizeof(char));
char *p;
strcpy(res,path);
@@ -1372,7 +1393,7 @@ static char *path_massage(char *long_path)
{
char *p;
- p = malloc(MAX_PATH+1);
+ p = emalloc(MAX_PATH+1);
strcpy(p, long_path);
GetShortPathName(p, p, MAX_PATH);
return p;
@@ -1508,7 +1529,8 @@ get_parameters(int argc, char** argv)
/* Determine bindir from absolute path to executable */
char *p;
char buffer[PATH_MAX];
- strcpy(buffer, argv[0]);
+ strncpy(buffer, argv[0], sizeof(buffer));
+ buffer[sizeof(buffer)-1] = '\0';
for (p = buffer+strlen(buffer)-1 ; p >= buffer && *p != '/'; --p)
;
@@ -1521,7 +1543,8 @@ get_parameters(int argc, char** argv)
/* Determine rootdir from absolute path to bindir */
char *p;
char buffer[PATH_MAX];
- strcpy(buffer, bindir);
+ strncpy(buffer, bindir, sizeof(buffer));
+ buffer[sizeof(buffer)-1] = '\0';
for (p = buffer+strlen(buffer)-1; p >= buffer && *p != '/'; --p)
;
diff --git a/erts/etc/common/escript.c b/erts/etc/common/escript.c
index 1bc5eb7651..6ed79c91e3 100644
--- a/erts/etc/common/escript.c
+++ b/erts/etc/common/escript.c
@@ -151,6 +151,9 @@ find_prog(char *origpath)
char relpath[PMAX];
char abspath[PMAX];
+ if (strlen(origpath) >= sizeof(relpath))
+ error("Path too long");
+
strcpy(relpath, origpath);
if (strstr(relpath, DIRSEPSTR) == NULL) {
@@ -180,19 +183,21 @@ find_prog(char *origpath)
end = strstr(beg, PATHSEPSTR);
if (end != NULL) {
sz = end - beg;
- strncpy(dir, beg, sz);
- dir[sz] = '\0';
} else {
sz = strlen(beg);
- strcpy(dir, beg);
look_for_sep = FALSE;
}
+ if (sz >= sizeof(dir)) {
+ beg = end + 1;
+ continue;
+ }
+ strncpy(dir, beg, sz);
+ dir[sz] = '\0';
beg = end + 1;
#ifdef __WIN32__
- strcpy(wildcard, dir);
- strcat(wildcard, DIRSEPSTR);
- strcat(wildcard, relpath); /* basename */
+ erts_snprintf(wildcard, sizeof(wildcard), "%s" DIRSEPSTR "%s",
+ dir, relpath /* basename */);
dir_handle = FindFirstFile(wildcard, &find_data);
if (dir_handle == INVALID_HANDLE_VALUE) {
/* Try next directory in path */
@@ -217,9 +222,8 @@ find_prog(char *origpath)
if (strcmp(origpath, dirp->d_name) == 0) {
/* Wow we found the executable. */
- strcpy(relpath, dir);
- strcat(relpath, DIRSEPSTR);
- strcat(relpath, dirp->d_name);
+ erts_snprintf(relpath, sizeof(relpath), "%s" DIRSEPSTR "%s",
+ dir, dirp->d_name);
closedir(dp);
look_for_sep = FALSE;
break;
@@ -291,7 +295,7 @@ append_shebang_args(char* scriptname)
/* Find end of arg */
end = beg;
- while (end && end[0] != ' ') {
+ while (end && end < (linebuf+LINEBUFSZ-1) && end[0] != ' ') {
if (end[0] == '\n') {
newline = TRUE;
end[0]= '\0';
@@ -335,13 +339,16 @@ main(int argc, char** argv)
emulator = get_default_emulator(argv[0]);
}
+ if (strlen(emulator) >= PMAX)
+ error("Value of environment variable ESCRIPT_EMULATOR is too large");
+
/*
* Allocate the argv vector to be used for arguments to Erlang.
* Arrange for starting to pushing information in the middle of
* the array, to allow easy addition of commands in the beginning.
*/
- eargv_size = argc*4+1000;
+ eargv_size = argc*4+1000+LINEBUFSZ/2;
eargv_base = (char **) emalloc(eargv_size*sizeof(char*));
eargv = eargv_base;
eargc = 0;
@@ -387,7 +394,8 @@ main(int argc, char** argv)
if (argc <= 1) {
error("Missing filename\n");
}
- strcpy(scriptname, argv[1]);
+ strncpy(scriptname, argv[1], sizeof(scriptname));
+ scriptname[sizeof(scriptname)-1] = '\0';
argc--;
argv++;
} else {
@@ -395,16 +403,17 @@ main(int argc, char** argv)
int len;
#endif
absname = find_prog(argv[0]);
- strcpy(scriptname, absname);
- efree(absname);
#ifdef __WIN32__
- len = strlen(scriptname);
- if (len >= 4 && _stricmp(scriptname+len-4, ".exe") == 0) {
- scriptname[len-4] = '\0';
+ len = strlen(absname);
+ if (len >= 4 && _stricmp(absname+len-4, ".exe") == 0) {
+ absname[len-4] = '\0';
}
#endif
- strcat(scriptname, ".escript");
+ erts_snprintf(scriptname, sizeof(scriptname), "%s.escript",
+ absname);
+ efree(absname);
+
}
/*
@@ -455,7 +464,7 @@ main(int argc, char** argv)
static void
push_words(char* src)
{
- char sbuf[1024];
+ char sbuf[PMAX];
char* dst;
dst = sbuf;
@@ -584,7 +593,7 @@ error(char* format, ...)
va_list ap;
va_start(ap, format);
- vsprintf(sbuf, format, ap);
+ erts_vsnprintf(sbuf, sizeof(sbuf), format, ap);
va_end(ap);
fprintf(stderr, "escript: %s\n", sbuf);
exit(1);
@@ -619,6 +628,9 @@ get_default_emulator(char* progname)
char sbuf[MAXPATHLEN];
char* s;
+ if (strlen(progname) >= sizeof(sbuf))
+ return ERL_NAME;
+
strcpy(sbuf, progname);
for (s = sbuf+strlen(sbuf); s >= sbuf; s--) {
if (IS_DIRSEP(*s)) {
diff --git a/erts/etc/common/heart.c b/erts/etc/common/heart.c
index 4f738947b7..3e19e5f386 100644
--- a/erts/etc/common/heart.c
+++ b/erts/etc/common/heart.c
@@ -375,7 +375,8 @@ main(int argc, char **argv)
_setmode(erlin_fd,_O_BINARY);
_setmode(erlout_fd,_O_BINARY);
#endif
- strcpy(program_name, argv[0]);
+ strncpy(program_name, argv[0], sizeof(program_name));
+ program_name[sizeof(program_name)-1] = '\0';
notify_ack(erlout_fd);
cmd[0] = '\0';
do_terminate(message_loop(erlin_fd,erlout_fd));
@@ -728,7 +729,11 @@ heart_cmd_reply(int fd, char *s)
struct msg m;
int len = strlen(s) + 1; /* Include \0 */
- /* FIXME if s >= MSG_BODY_SIZE error */
+ /* if s >= MSG_BODY_SIZE, return a write
+ * failure immediately.
+ */
+ if (len > sizeof(m.fill))
+ return -1;
m.op = HEART_CMD;
m.len = htons(len + 2); /* Include Op */
diff --git a/erts/etc/common/inet_gethost.c b/erts/etc/common/inet_gethost.c
index d3ff4874ac..e095836258 100644
--- a/erts/etc/common/inet_gethost.c
+++ b/erts/etc/common/inet_gethost.c
@@ -59,6 +59,7 @@
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <windows.h>
+#include <ws2tcpip.h>
#include <process.h>
#include <stdio.h>
#include <stdlib.h>
diff --git a/erts/etc/common/run_test.c b/erts/etc/common/run_test.c
index 016d9c6afd..042b8571ca 100644
--- a/erts/etc/common/run_test.c
+++ b/erts/etc/common/run_test.c
@@ -164,11 +164,13 @@ main(int argc, char** argv)
erl_args = cnt;
}
else if (strcmp(argv[1], "-sname") == 0) {
- strcpy(nodename, argv[2]);
+ strncpy(nodename, argv[2], sizeof(nodename));
+ nodename[sizeof(nodename)-1] = '\0';
cnt++, argv++;
}
else if (strcmp(argv[1], "-name") == 0) {
- strcpy(nodename, argv[2]);
+ strncpy(nodename, argv[2], sizeof(nodename));
+ nodename[sizeof(nodename)-1] = '\0';
dist_mode = FULL_NAME;
cnt++, argv++;
}
@@ -178,7 +180,8 @@ main(int argc, char** argv)
ct_mode = VTS_MODE;
}
else if (strcmp(argv[1], "-browser") == 0) {
- strcpy(browser, argv[2]);
+ strncpy(browser, argv[2], sizeof(browser));
+ browser[sizeof(browser)-1] = '\0';
cnt++, argv++;
}
else if (strcmp(argv[1], "-shell") == 0) {
@@ -189,7 +192,8 @@ main(int argc, char** argv)
ct_mode = MASTER_MODE;
}
else if (strcmp(argv[1], "-ctname") == 0) {
- strcpy(nodename, argv[2]);
+ strncpy(nodename, argv[2], sizeof(nodename));
+ nodename[sizeof(nodename)-1] = '\0';
ct_mode = ERL_SHELL_MODE;
cnt++, argv++;
}
@@ -273,7 +277,7 @@ main(int argc, char** argv)
static void
push_words(char* src)
{
- char sbuf[1024];
+ char sbuf[MAXPATHLEN];
char* dst;
dst = sbuf;
@@ -405,7 +409,7 @@ error(char* format, ...)
va_list ap;
va_start(ap, format);
- vsprintf(sbuf, format, ap);
+ erts_vsnprintf(sbuf, sizeof(sbuf), format, ap);
va_end(ap);
fprintf(stderr, "run_test: %s\n", sbuf);
exit(1);
@@ -434,6 +438,9 @@ get_default_emulator(char* progname)
char sbuf[MAXPATHLEN];
char* s;
+ if (strlen(progname) >= sizeof(sbuf))
+ return ERL_NAME;
+
strcpy(sbuf, progname);
for (s = sbuf+strlen(sbuf); s >= sbuf; s--) {
if (IS_DIRSEP(*s)) {
diff --git a/erts/etc/common/typer.c b/erts/etc/common/typer.c
index c2567cb8b4..de48daf002 100644
--- a/erts/etc/common/typer.c
+++ b/erts/etc/common/typer.c
@@ -175,7 +175,7 @@ main(int argc, char** argv)
static void
push_words(char* src)
{
- char sbuf[1024];
+ char sbuf[MAXPATHLEN];
char* dst;
dst = sbuf;
@@ -307,7 +307,7 @@ error(char* format, ...)
va_list ap;
va_start(ap, format);
- vsprintf(sbuf, format, ap);
+ erts_vsnprintf(sbuf, sizeof(sbuf), format, ap);
va_end(ap);
fprintf(stderr, "typer: %s\n", sbuf);
exit(1);
@@ -336,6 +336,9 @@ get_default_emulator(char* progname)
char sbuf[MAXPATHLEN];
char* s;
+ if (strlen(progname) >= sizeof(sbuf))
+ return ERL_NAME;
+
strcpy(sbuf, progname);
for (s = sbuf+strlen(sbuf); s >= sbuf; s--) {
if (IS_DIRSEP(*s)) {
diff --git a/erts/etc/unix/cerl.src b/erts/etc/unix/cerl.src
index 9dab9fcfcc..73b1bafbe0 100644
--- a/erts/etc/unix/cerl.src
+++ b/erts/etc/unix/cerl.src
@@ -66,6 +66,7 @@ core=
GDB=
GDBBP=
+GDBARGS=
TYPE=
EMU_TYPE=
debug=
@@ -280,16 +281,11 @@ else
# Set annotation level for gdb in emacs 22 and higher.
emacs_major=`$EMACS --version | head -1 | sed 's,^[^0-9]*\([0-9]*\).*,\1,g'`
if [ '!' -z "$emacs_major" -a $emacs_major -gt 21 ]; then
- # Hack - wait for etp-commands to be loaded and then set
- # annotation level, could be done more beautifully than with sit-for...
- gdbcmd="$gdbcmd \
- (sit-for 1) \
- (insert-string \"set annotate 3\") \
- (comint-send-input)"
+ GDBARGS="--annotate=3 "
fi
gdbcmd="$gdbcmd $GDBBP \
(insert-string \"source $ROOTDIR/erts/etc/unix/etp-commands\") \
(comint-send-input)"
# Fire up gdb in emacs...
- exec $EMACS --eval "(progn (gdb \"gdb $EMU\") $gdbcmd)"
+ exec $EMACS --eval "(progn (gdb \"gdb $GDBARGS$EMU\") $gdbcmd)"
fi
diff --git a/erts/etc/unix/run_erl.c b/erts/etc/unix/run_erl.c
index 4bb148df98..cadff12c6f 100644
--- a/erts/etc/unix/run_erl.c
+++ b/erts/etc/unix/run_erl.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2010. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -75,6 +75,9 @@
#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif
+#if defined(__sun) && defined(__SVR4)
+# include <stropts.h>
+#endif
#include "run_erl.h"
#include "safe_string.h" /* sn_printf, strn_cpy, strn_cat, etc */
@@ -864,8 +867,12 @@ static int open_pty_master(char **ptyslave)
/* Use the posix_openpt if working, as this guarantees creation of the
slave device properly. */
-#ifdef HAVE_WORKING_POSIX_OPENPT
+#if defined(HAVE_WORKING_POSIX_OPENPT) || (defined(__sun) && defined(__SVR4))
+# ifdef HAVE_WORKING_POSIX_OPENPT
if ((mfd = posix_openpt(O_RDWR)) >= 0) {
+# elif defined(__sun) && defined(__SVR4)
+ if ((mfd = open("/dev/ptmx", O_RDWR)) >= 0) {
+# endif
if ((*ptyslave = ptsname(mfd)) != NULL &&
grantpt(mfd) == 0 &&
unlockpt(mfd) == 0) {
@@ -981,8 +988,28 @@ static int open_pty_slave(char *name)
return -1;
}
+#if defined(__sun) && defined(__SVR4)
+ /* Load the necessary STREAMS modules for Solaris */
+ if ((ioctl(sfd, I_FIND, "ldterm")) < 0) {
+ ERROR0(LOG_ERR, "Failed to find ldterm STREAMS module");
+ return -1;
+ }
+ if (ioctl(sfd, I_PUSH, "ptem") < 0) {
+ ERROR0(LOG_ERR, "Failed to push ptem STREAMS module");
+ return -1;
+ }
+ if (ioctl(sfd, I_PUSH, "ldterm") < 0) {
+ ERROR0(LOG_ERR, "Failed to push ldterm STREAMS module");
+ return -1;
+ }
+ if (ioctl(sfd, I_PUSH, "ttcompat") < 0) {
+ ERROR0(LOG_ERR, "Failed to push ttcompat STREAMS module");
+ return -1;
+ }
+#endif
+
#ifdef DEBUG
- if (tcgetattr(sfd, &tty_rmode) , 0) {
+ if (tcgetattr(sfd, &tty_rmode) < 0) {
fprintf(stderr, "Cannot get terminals current mode\n");
exit(-1);
}
diff --git a/erts/etc/win32/cygwin_tools/vc/ld.sh b/erts/etc/win32/cygwin_tools/vc/ld.sh
index ac39bf871c..9a38c10748 100755
--- a/erts/etc/win32/cygwin_tools/vc/ld.sh
+++ b/erts/etc/win32/cygwin_tools/vc/ld.sh
@@ -3,7 +3,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2002-2009. All Rights Reserved.
+# Copyright Ericsson AB 2002-2010. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -53,7 +53,7 @@ while test -n "$1" ; do
STDLIB_FORCED=true;
STDLIB=LIBCMTD.LIB;;
-lsocket)
- DEFAULT_LIBRARIES="$DEFAULT_LIBRARIES WS2_32.LIB";;
+ DEFAULT_LIBRARIES="$DEFAULT_LIBRARIES WS2_32.LIB IPHLPAPI.LIB";;
-l*)
y=`echo $x | sed 's,^-l\(.*\),\1,g'`;
MPATH=`cygpath -m $y`;
@@ -167,6 +167,10 @@ eval link.exe "$CMD" >/tmp/link.exe.${p}.1 2>/tmp/link.exe.${p}.2
RES=$?
CMANIFEST=`cygpath $MANIFEST`
if [ "$RES" = "0" -a -f "$CMANIFEST" ]; then
+ # Add stuff to manifest to turn off "virtualization"
+ sed -n -i '1h;1!H;${;g;s,<trustInfo.*</trustInfo>.,,g;p;}' $CMANIFEST
+ sed -i "s/<\/assembly>/ <ms_asmv2:trustInfo xmlns:ms_asmv2=\"urn:schemas-microsoft-com:asm.v2\">\n <ms_asmv2:security>\n <ms_asmv2:requestedPrivileges>\n <ms_asmv2:requestedExecutionLevel level=\"AsInvoker\" uiAccess=\"false\"\/>\n <\/ms_asmv2:requestedPrivileges>\n <\/ms_asmv2:security>\n <\/ms_asmv2:trustInfo>\n<\/assembly>/" $CMANIFEST
+
eval mt.exe -nologo -manifest "$MANIFEST" -outputresource:"$OUTPUTRES" >>/tmp/link.exe.${p}.1 2>>/tmp/link.exe.${p}.2
RES=$?
if [ "$RES" != "0" ]; then
diff --git a/erts/include/internal/erl_misc_utils.h b/erts/include/internal/erl_misc_utils.h
index 6b875ff824..507e1726f4 100644
--- a/erts/include/internal/erl_misc_utils.h
+++ b/erts/include/internal/erl_misc_utils.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2006-2009. All Rights Reserved.
+ * Copyright Ericsson AB 2006-2010. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -34,7 +34,7 @@ typedef struct {
erts_cpu_info_t *erts_cpu_info_create(void);
void erts_cpu_info_destroy(erts_cpu_info_t *cpuinfo);
-void erts_cpu_info_update(erts_cpu_info_t *cpuinfo);
+int erts_cpu_info_update(erts_cpu_info_t *cpuinfo);
int erts_get_cpu_configured(erts_cpu_info_t *cpuinfo);
int erts_get_cpu_online(erts_cpu_info_t *cpuinfo);
int erts_get_cpu_available(erts_cpu_info_t *cpuinfo);
@@ -51,6 +51,7 @@ int erts_unbind_from_cpu_str(char *str);
int erts_milli_sleep(long);
#ifdef __WIN32__
+int erts_map_win_error_to_errno(DWORD win_error);
int erts_get_last_win_errno(void);
#endif
diff --git a/erts/include/internal/ethr_mutex.h b/erts/include/internal/ethr_mutex.h
index 4ce3e75c78..8d9d5e3d08 100644
--- a/erts/include/internal/ethr_mutex.h
+++ b/erts/include/internal/ethr_mutex.h
@@ -346,7 +346,9 @@ do { \
#ifdef ETHR_USE_OWN_MTX_IMPL__
-#define ETHR_MTX_DEFAULT_MAIN_SPINCOUNT 1000
+#define ETHR_MTX_DEFAULT_MAIN_SPINCOUNT_MAX 2000
+#define ETHR_MTX_DEFAULT_MAIN_SPINCOUNT_BASE 800
+#define ETHR_MTX_DEFAULT_MAIN_SPINCOUNT_INC 50
#define ETHR_MTX_DEFAULT_AUX_SPINCOUNT 50
#define ETHR_CND_DEFAULT_MAIN_SPINCOUNT 0
@@ -443,7 +445,9 @@ ETHR_INLINE_FUNC_NAME_(ethr_mutex_unlock)(ethr_mutex *mtx)
#ifdef ETHR_USE_OWN_RWMTX_IMPL__
-#define ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT 1000
+#define ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT_MAX 2000
+#define ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT_BASE 800
+#define ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT_INC 50
#define ETHR_RWMTX_DEFAULT_AUX_SPINCOUNT 50
#else /* pthread_rwlock */
diff --git a/erts/include/internal/ethread.h b/erts/include/internal/ethread.h
index 4a205699bd..931d692908 100644
--- a/erts/include/internal/ethread.h
+++ b/erts/include/internal/ethread.h
@@ -239,6 +239,8 @@ typedef DWORD ethr_tsd_key;
# include "gcc/ethread.h"
# include "libatomic_ops/ethread.h"
# endif
+# elif defined(ETHR_HAVE_LIBATOMIC_OPS)
+# include "libatomic_ops/ethread.h"
# elif defined(ETHR_WIN32_THREADS)
# include "win/ethread.h"
# endif
diff --git a/erts/include/internal/gcc/ethr_atomic.h b/erts/include/internal/gcc/ethr_atomic.h
index 5fe6e23477..e8e529dd48 100644
--- a/erts/include/internal/gcc/ethr_atomic.h
+++ b/erts/include/internal/gcc/ethr_atomic.h
@@ -31,7 +31,7 @@
#define ETHR_IMMED_ATOMIC_SET_GET_SAFE__ 0
/* Enable immediate read/write on platforms where we know it is safe */
#if defined(__i386__) || defined(__x86_64__) || defined(__sparc__) \
- || defined(__powerpc__) || defined(__ppc__)
+ || defined(__powerpc__) || defined(__ppc__) || defined(__mips__)
# undef ETHR_IMMED_ATOMIC_SET_GET_SAFE__
# define ETHR_IMMED_ATOMIC_SET_GET_SAFE__ 1
#endif
@@ -48,13 +48,18 @@ typedef struct {
* a noop on at least some platforms with some gcc versions.
* This has suposedly been fixed in some gcc version, but we
* don't know from which version. Therefore, we use the
- * workaround implemented below on all gcc versions.
+ * workaround implemented below on all gcc versions except
+ * for gcc 4.2 or above for MIPS, where it's been verified.
*/
+#if defined(__mips__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))
+#define ETHR_MEMORY_BARRIER __sync_synchronize()
+#else
#define ETHR_MEMORY_BARRIER \
do { \
volatile long x___ = 0; \
(void) __sync_val_compare_and_swap(&x___, (long) 0, (long) 1); \
} while (0)
+#endif
#define ETHR_READ_DEPEND_MEMORY_BARRIER ETHR_MEMORY_BARRIER
#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_AUX_IMPL__)
diff --git a/erts/lib_src/common/erl_misc_utils.c b/erts/lib_src/common/erl_misc_utils.c
index d2ef7140a5..4c881993a5 100644
--- a/erts/lib_src/common/erl_misc_utils.c
+++ b/erts/lib_src/common/erl_misc_utils.c
@@ -21,10 +21,13 @@
#include "config.h"
#endif
+#if defined(__WIN32__)
+# include <windows.h>
+#endif
+
#include "erl_misc_utils.h"
#if defined(__WIN32__)
-# include <windows.h>
#elif defined(VXWORKS)
# include <selectLib.h>
#else /* UNIX */
@@ -62,12 +65,25 @@
#if defined(HAVE_SCHED_xETAFFINITY)
# include <sched.h>
# define ERTS_HAVE_MISC_UTIL_AFFINITY_MASK__
-#define ERTS_MU_GET_PROC_AFFINITY__(CPUINFOP) \
+#define ERTS_MU_GET_PROC_AFFINITY__(CPUINFOP, CPUSET) \
(sched_getaffinity((CPUINFOP)->pid, \
sizeof(cpu_set_t), \
- &(CPUINFOP)->cpuset) != 0 ? -errno : 0)
+ (CPUSET)) != 0 ? -errno : 0)
#define ERTS_MU_SET_THR_AFFINITY__(SETP) \
(sched_setaffinity(0, sizeof(cpu_set_t), (SETP)) != 0 ? -errno : 0)
+#elif defined(HAVE_CPUSET_xETAFFINITY)
+# include <sys/param.h>
+# include <sys/cpuset.h>
+# define ERTS_HAVE_MISC_UTIL_AFFINITY_MASK__
+#define ERTS_MU_GET_PROC_AFFINITY__(CPUINFOP, CPUSET) \
+ (cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, \
+ sizeof(cpuset_t), \
+ (CPUSET)) != 0 ? -errno : 0)
+#define ERTS_MU_SET_THR_AFFINITY__(CPUSETP) \
+ (cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, \
+ sizeof(cpuset_t), \
+ (CPUSETP)) != 0 ? -errno : 0)
+# define cpu_set_t cpuset_t
#elif defined(__WIN32__)
# define ERTS_HAVE_MISC_UTIL_AFFINITY_MASK__
# define cpu_set_t DWORD
@@ -97,8 +113,33 @@
# define ERTS_SYS_CPU_PATH "/sys/devices/system/cpu"
#endif
+#ifdef __FreeBSD__
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#endif
+
static int read_topology(erts_cpu_info_t *cpuinfo);
+#if defined(ERTS_HAVE_MISC_UTIL_AFFINITY_MASK__)
+static int
+cpu_sets_are_eq(cpu_set_t *x, cpu_set_t *y)
+{
+ int i;
+ for (i = 0; i < CPU_SETSIZE; i++) {
+ if (CPU_ISSET(i, x)) {
+ if (!CPU_ISSET(i, y))
+ return 0;
+ }
+ else {
+ if (CPU_ISSET(i, y))
+ return 0;
+ }
+ }
+ return 1;
+}
+
+#endif
+
int
erts_milli_sleep(long ms)
{
@@ -137,15 +178,15 @@ struct erts_cpu_info_t_ {
#if defined(__WIN32__)
static __forceinline int
-get_proc_affinity(erts_cpu_info_t *cpuinfo)
+get_proc_affinity(erts_cpu_info_t *cpuinfo, cpu_set_t *cpuset)
{
DWORD pamask, samask;
if (GetProcessAffinityMask(GetCurrentProcess(), &pamask, &samask)) {
- cpuinfo->cpuset = (cpu_set_t) pamask;
+ *cpuset = (cpu_set_t) pamask;
return 0;
}
else {
- cpuinfo->cpuset = (cpu_set_t) 0;
+ *cpuset = (cpu_set_t) 0;
return -erts_get_last_win_errno();
}
}
@@ -179,6 +220,9 @@ erts_cpu_info_create(void)
#endif
cpuinfo->topology_size = 0;
cpuinfo->topology = NULL;
+ cpuinfo->configured = -1;
+ cpuinfo->online = -1;
+ cpuinfo->available = -1;
erts_cpu_info_update(cpuinfo);
return cpuinfo;
}
@@ -203,34 +247,40 @@ erts_cpu_info_destroy(erts_cpu_info_t *cpuinfo)
}
}
-void
+int
erts_cpu_info_update(erts_cpu_info_t *cpuinfo)
{
- cpuinfo->configured = 0;
- cpuinfo->online = 0;
- cpuinfo->available = 0;
+ int changed = 0;
+ int configured = 0;
+ int online = 0;
+ int available = 0;
+ erts_cpu_topology_t *old_topology;
+ int old_topology_size;
+#if defined(ERTS_HAVE_MISC_UTIL_AFFINITY_MASK__)
+ cpu_set_t cpuset;
+#endif
#ifdef __WIN32__
{
int i;
SYSTEM_INFO sys_info;
GetSystemInfo(&sys_info);
- cpuinfo->configured = (int) sys_info.dwNumberOfProcessors;
+ configured = (int) sys_info.dwNumberOfProcessors;
for (i = 0; i < sizeof(DWORD)*8; i++)
if (sys_info.dwActiveProcessorMask & (((DWORD) 1) << i))
- cpuinfo->online++;
+ online++;
}
#elif !defined(NO_SYSCONF) && (defined(_SC_NPROCESSORS_CONF) \
|| defined(_SC_NPROCESSORS_ONLN))
#ifdef _SC_NPROCESSORS_CONF
- cpuinfo->configured = (int) sysconf(_SC_NPROCESSORS_CONF);
- if (cpuinfo->configured < 0)
- cpuinfo->configured = 0;
+ configured = (int) sysconf(_SC_NPROCESSORS_CONF);
+ if (configured < 0)
+ configured = 0;
#endif
#ifdef _SC_NPROCESSORS_ONLN
- cpuinfo->online = (int) sysconf(_SC_NPROCESSORS_ONLN);
- if (cpuinfo->online < 0)
- cpuinfo->online = 0;
+ online = (int) sysconf(_SC_NPROCESSORS_ONLN);
+ if (online < 0)
+ online = 0;
#endif
#elif defined(HAVE_SYS_SYSCTL_H) && defined(CTL_HW) && (defined(HW_NCPU) \
|| defined(HW_AVAILCPU))
@@ -242,71 +292,138 @@ erts_cpu_info_update(erts_cpu_info_t *cpuinfo)
len = sizeof(int);
mib[0] = CTL_HW;
mib[1] = HW_NCPU;
- if (sysctl(&mib[0], 2, &cpuinfo->configured, &len, NULL, 0) < 0)
- cpuinfo->configured = 0;
+ if (sysctl(&mib[0], 2, &configured, &len, NULL, 0) < 0)
+ configured = 0;
#endif
#ifdef HW_AVAILCPU
len = sizeof(int);
mib[0] = CTL_HW;
mib[1] = HW_AVAILCPU;
- if (sysctl(&mib[0], 2, &cpuinfo->online, &len, NULL, 0) < 0)
- cpuinfo->online = 0;
+ if (sysctl(&mib[0], 2, &online, &len, NULL, 0) < 0)
+ online = 0;
#endif
}
#endif
- if (cpuinfo->online > cpuinfo->configured)
- cpuinfo->online = cpuinfo->configured;
+ if (online > configured)
+ online = configured;
+
+ if (cpuinfo->configured != configured)
+ changed = 1;
+ if (cpuinfo->online != online)
+ changed = 1;
#if defined(ERTS_HAVE_MISC_UTIL_AFFINITY_MASK__)
- if (ERTS_MU_GET_PROC_AFFINITY__(cpuinfo) == 0) {
- int i, c, cn, si;
- c = cn = 0;
- si = sizeof(cpuinfo->affinity_str_buf) - 1;
- cpuinfo->affinity_str_buf[si] = '\0';
- for (i = 0; i < CPU_SETSIZE; i++) {
- if (CPU_ISSET(i, &cpuinfo->cpuset)) {
- c |= 1 << cn;
- cpuinfo->available++;
+ if (ERTS_MU_GET_PROC_AFFINITY__(cpuinfo, &cpuset) == 0) {
+ if (!changed && !cpu_sets_are_eq(&cpuset, &cpuinfo->cpuset))
+ changed = 1;
+
+ if (!changed)
+ available = cpuinfo->available;
+ else {
+ int i, c, cn, si;
+
+ memcpy((void *) &cpuinfo->cpuset,
+ (void *) &cpuset,
+ sizeof(cpu_set_t));
+
+ c = cn = 0;
+ si = sizeof(cpuinfo->affinity_str_buf) - 1;
+ cpuinfo->affinity_str_buf[si] = '\0';
+ for (i = 0; i < CPU_SETSIZE; i++) {
+ if (CPU_ISSET(i, &cpuinfo->cpuset)) {
+ c |= 1 << cn;
+ available++;
+ }
+ cn++;
+ if (cn == 4) {
+ cpuinfo->affinity_str_buf[--si] = (c < 10
+ ? '0' + c
+ : 'A' + c - 10);
+ c = cn = 0;
+ }
}
- cn++;
- if (cn == 4) {
+ if (c)
cpuinfo->affinity_str_buf[--si] = (c < 10
? '0' + c
: 'A' + c - 10);
- c = cn = 0;
- }
+ while (cpuinfo->affinity_str_buf[si] == '0')
+ si++;
+ cpuinfo->affinity_str = &cpuinfo->affinity_str_buf[si];
}
- if (c)
- cpuinfo->affinity_str_buf[--si] = (c < 10
- ? '0' + c
- : 'A' + c - 10);
- while (cpuinfo->affinity_str_buf[si] == '0')
- si++;
- cpuinfo->affinity_str = &cpuinfo->affinity_str_buf[si];
}
#elif defined(HAVE_PSET_INFO)
{
- uint_t numcpus = cpuinfo->configured;
- if (cpuinfo->cpuids)
- free(cpuinfo->cpuids);
- cpuinfo->cpuids = malloc(sizeof(processorid_t)*numcpus);
- if (cpuinfo->cpuids) {
- if (pset_info(PS_MYID, NULL, &numcpus, &cpuinfo->cpuids) == 0)
- cpuinfo->available = (int) numcpus;
- if (cpuinfo->available < 0) {
- free(cpuinfo->cpuid);
- cpuinfo->available = 0;
+ processorid_t *cpuids;
+ uint_t numcpus = configured;
+ cpuids = malloc(sizeof(processorid_t)*numcpus);
+ if (cpuids) {
+ if (pset_info(PS_MYID, NULL, &numcpus, &cpuids) == 0)
+ available = (int) numcpus;
+ if (available < 0) {
+ free(cpuids);
+ cpuids = NULL;
+ available = 0;
}
}
+ if (!cpuids) {
+ if (cpuinfo->cpuids)
+ changed = 1;
+ }
+ else {
+ if (cpuinfo->cpuids)
+ changed = 1;
+ if (memcmp((void *) cpuinfo->cpuids,
+ (void *) cpuids,
+ sizeof(processorid_t)*numcpus) != 0)
+ changed = 1;
+
+ }
+ if (!changed) {
+ if (cpuids)
+ free(cpuids);
+ }
+ else {
+ if (cpuinfo->cpuids)
+ free(cpuinfo->cpuids);
+ cpuinfo->cpuids = cpuids;
+ }
}
#endif
- if (cpuinfo->available > cpuinfo->online)
- cpuinfo->available = cpuinfo->online;
+ if (available > online)
+ available = online;
+
+ if (cpuinfo->available != available)
+ changed = 1;
+
+ cpuinfo->configured = configured;
+ cpuinfo->online = online;
+ cpuinfo->available = available;
+
+ old_topology = cpuinfo->topology;
+ old_topology_size = cpuinfo->topology_size;
+ cpuinfo->topology = NULL;
read_topology(cpuinfo);
+ if (cpuinfo->topology_size != old_topology_size
+ || (old_topology_size != 0
+ && memcmp((void *) cpuinfo->topology,
+ (void *) old_topology,
+ (sizeof(erts_cpu_topology_t)
+ * old_topology_size)) != 0)) {
+ changed = 1;
+ if (old_topology)
+ free(old_topology);
+ }
+ else {
+ if (cpuinfo->topology)
+ free(cpuinfo->topology);
+ cpuinfo->topology = old_topology;
+ }
+
+ return changed;
}
int
@@ -588,6 +705,56 @@ cpu_cmp(const void *vx, const void *vy)
return 0;
}
+static void
+adjust_processor_nodes(erts_cpu_info_t *cpuinfo, int no_nodes)
+{
+ erts_cpu_topology_t *prev, *this, *last;
+ if (no_nodes > 1) {
+ int processor = -1;
+ int processor_node = 0;
+ int node = -1;
+
+ qsort(cpuinfo->topology,
+ cpuinfo->topology_size,
+ sizeof(erts_cpu_topology_t),
+ pn_cmp);
+
+ prev = NULL;
+ this = &cpuinfo->topology[0];
+ last = &cpuinfo->topology[cpuinfo->configured-1];
+ while (1) {
+ if (processor == this->processor) {
+ if (node != this->node)
+ processor_node = 1;
+ }
+ else {
+ if (processor_node) {
+ make_processor_node:
+ while (prev->processor == processor) {
+ prev->processor_node = prev->node;
+ prev->node = -1;
+ if (prev == &cpuinfo->topology[0])
+ break;
+ prev--;
+ }
+ processor_node = 0;
+ }
+ processor = this->processor;
+ node = this->node;
+ }
+ if (this == last) {
+ if (processor_node) {
+ prev = this;
+ goto make_processor_node;
+ }
+ break;
+ }
+ prev = this++;
+ }
+ }
+}
+
+
#ifdef __linux__
static int
@@ -641,9 +808,6 @@ read_topology(erts_cpu_info_t *cpuinfo)
errno = 0;
- if (cpuinfo->topology)
- free(cpuinfo->topology);
-
if (cpuinfo->configured < 1)
goto error;
@@ -757,49 +921,7 @@ read_topology(erts_cpu_info_t *cpuinfo)
cpuinfo->topology = t;
}
- if (no_nodes > 1) {
- int processor = -1;
- int processor_node = 0;
- int node = -1;
-
- qsort(cpuinfo->topology,
- cpuinfo->topology_size,
- sizeof(erts_cpu_topology_t),
- pn_cmp);
-
- prev = NULL;
- this = &cpuinfo->topology[0];
- last = &cpuinfo->topology[cpuinfo->configured-1];
- while (1) {
- if (processor == this->processor) {
- if (node != this->node)
- processor_node = 1;
- }
- else {
- if (processor_node) {
- make_processor_node:
- while (prev->processor == processor) {
- prev->processor_node = prev->node;
- prev->node = -1;
- if (prev == &cpuinfo->topology[0])
- break;
- prev--;
- }
- processor_node = 0;
- }
- processor = this->processor;
- node = this->node;
- }
- if (this == last) {
- if (processor_node) {
- prev = this;
- goto make_processor_node;
- }
- break;
- }
- prev = this++;
- }
- }
+ adjust_processor_nodes(cpuinfo, no_nodes);
qsort(cpuinfo->topology,
cpuinfo->topology_size,
@@ -896,9 +1018,6 @@ read_topology(erts_cpu_info_t *cpuinfo)
errno = 0;
- if (cpuinfo->topology)
- free(cpuinfo->topology);
-
if (cpuinfo->configured < 1)
goto error;
@@ -985,6 +1104,8 @@ read_topology(erts_cpu_info_t *cpuinfo)
}
}
+ adjust_processor_nodes(cpuinfo, 1);
+
error:
if (res == 0) {
@@ -1003,6 +1124,519 @@ read_topology(erts_cpu_info_t *cpuinfo)
}
+#elif defined(__WIN32__)
+
+/*
+ * We cannot use Relation* out of the box since all of them are not
+ * always part of the LOGICAL_PROCESSOR_RELATIONSHIP enum. They are
+ * however documented as follows...
+ */
+#define ERTS_MU_RELATION_PROCESSOR_CORE 0 /* RelationProcessorCore */
+#define ERTS_MU_RELATION_NUMA_NODE 1 /* RelationNumaNode */
+#define ERTS_MU_RELATION_CACHE 2 /* RelationCache */
+#define ERTS_MU_RELATION_PROCESSOR_PACKAGE 3 /* RelationProcessorPackage */
+
+static __forceinline int
+rel_cmp_val(int r)
+{
+ switch (r) {
+ case ERTS_MU_RELATION_NUMA_NODE: return 0;
+ case ERTS_MU_RELATION_PROCESSOR_PACKAGE: return 1;
+ case ERTS_MU_RELATION_PROCESSOR_CORE: return 2;
+ default: /* currently not used */ return 3;
+ }
+}
+
+static int
+slpi_cmp(const void *vx, const void *vy)
+{
+ PSYSTEM_LOGICAL_PROCESSOR_INFORMATION x, y;
+ x = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION) vx;
+ y = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION) vy;
+
+ if ((int) x->Relationship != (int) y->Relationship)
+ return (rel_cmp_val((int) x->Relationship)
+ - rel_cmp_val((int) y->Relationship));
+
+ switch ((int) x->Relationship) {
+ case ERTS_MU_RELATION_NUMA_NODE:
+ if (x->NumaNode.NodeNumber == y->NumaNode.NodeNumber)
+ break;
+ return ((int) x->NumaNode.NodeNumber) - ((int) y->NumaNode.NodeNumber);
+ case ERTS_MU_RELATION_PROCESSOR_CORE:
+ case ERTS_MU_RELATION_PROCESSOR_PACKAGE:
+ default:
+ break;
+ }
+
+ if (x->ProcessorMask == y->ProcessorMask)
+ return 0;
+ return x->ProcessorMask < y->ProcessorMask ? -1 : 1;
+}
+
+typedef BOOL (WINAPI *glpi_t)(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD);
+
+static int
+read_topology(erts_cpu_info_t *cpuinfo)
+{
+ int res = 0;
+ glpi_t glpi;
+ int *core_id = NULL;
+ PSYSTEM_LOGICAL_PROCESSOR_INFORMATION slpip = NULL;
+ int wix, rix, max_l, l, packages, nodes, no_slpi;
+ DWORD slpi_size = 0;
+
+
+ glpi = (glpi_t) GetProcAddress(GetModuleHandle("kernel32"),
+ "GetLogicalProcessorInformation");
+ if (!glpi)
+ return -ENOTSUP;
+
+ cpuinfo->topology = NULL;
+
+ if (cpuinfo->configured < 1 || sizeof(ULONG_PTR)*8 < cpuinfo->configured)
+ goto error;
+
+ while (1) {
+ DWORD werr;
+ if (TRUE == glpi(slpip, &slpi_size))
+ break;
+ werr = GetLastError();
+ if (werr != ERROR_INSUFFICIENT_BUFFER) {
+ res = -erts_map_win_error_to_errno(werr);
+ goto error;
+ }
+ if (slpip)
+ free(slpip);
+ slpip = malloc(slpi_size);
+ if (!slpip) {
+ res = -ENOMEM;
+ goto error;
+ }
+ }
+
+ no_slpi = (int) slpi_size/sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
+
+ qsort(slpip,
+ no_slpi,
+ sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION),
+ slpi_cmp);
+
+ /*
+ * Now numa node relations appear before package relations which
+ * appear before core relations which appear before relations
+ * we aren't interested in...
+ */
+
+ max_l = 0;
+ packages = 0;
+ nodes = 0;
+ for (rix = 0; rix < no_slpi; rix++) {
+ PSYSTEM_LOGICAL_PROCESSOR_INFORMATION this = &slpip[rix];
+ for (l = sizeof(ULONG_PTR)*8 - 1; l > 0; l--) {
+ if (slpip[rix].ProcessorMask & (((ULONG_PTR) 1) << l)) {
+ if (max_l < l)
+ max_l = l;
+ break;
+ }
+ }
+ if ((int) slpip[rix].Relationship == ERTS_MU_RELATION_PROCESSOR_PACKAGE)
+ packages++;
+ if ((int) slpip[rix].Relationship == ERTS_MU_RELATION_NUMA_NODE)
+ nodes++;
+ }
+
+ if (!packages) {
+ packages = 1;
+ }
+ core_id = malloc(sizeof(int)*packages);
+ if (!core_id) {
+ res = -ENOMEM;
+ goto error;
+ }
+
+ for (rix = 0; rix < packages; rix++)
+ core_id[rix] = 0;
+
+ cpuinfo->topology_size = max_l + 1;
+ cpuinfo->topology = malloc(sizeof(erts_cpu_topology_t)
+ * cpuinfo->topology_size);
+ if (!cpuinfo->topology) {
+ res = -ENOMEM;
+ goto error;
+ }
+
+ for (wix = 0; wix < cpuinfo->topology_size; wix++) {
+ cpuinfo->topology[wix].node = -1;
+ cpuinfo->topology[wix].processor = -1;
+ cpuinfo->topology[wix].processor_node = -1;
+ cpuinfo->topology[wix].core = -1;
+ cpuinfo->topology[wix].thread = -1;
+ cpuinfo->topology[wix].logical = -1;
+ }
+
+ nodes = 0;
+ packages = 0;
+
+ for (rix = 0; rix < no_slpi; rix++) {
+
+ switch ((int) slpip[rix].Relationship) {
+ case ERTS_MU_RELATION_NUMA_NODE:
+ for (l = 0; l < sizeof(ULONG_PTR)*8; l++) {
+ if (slpip[rix].ProcessorMask & (((ULONG_PTR) 1) << l)) {
+ cpuinfo->topology[l].logical = l;
+ cpuinfo->topology[l].node = slpip[rix].NumaNode.NodeNumber;
+ }
+ }
+ nodes++;
+ break;
+ case ERTS_MU_RELATION_PROCESSOR_PACKAGE:
+ for (l = 0; l < sizeof(ULONG_PTR)*8; l++) {
+ if (slpip[rix].ProcessorMask & (((ULONG_PTR) 1) << l)) {
+ cpuinfo->topology[l].logical = l;
+ cpuinfo->topology[l].processor = packages;
+ }
+ }
+ packages++;
+ break;
+ case ERTS_MU_RELATION_PROCESSOR_CORE: {
+ int thread = 0;
+ int processor = -1;
+ for (l = 0; l < sizeof(ULONG_PTR)*8; l++) {
+ /*
+ * Nodes and packages may not be supported; pretend
+ * that there are one if this is the case...
+ */
+ if (slpip[rix].ProcessorMask & (((ULONG_PTR) 1) << l)) {
+ if (!nodes) {
+ cpuinfo->topology[l].node = 0;
+ }
+ if (!packages) {
+ cpuinfo->topology[l].processor = 0;
+ }
+ if (processor < 0) {
+ processor = cpuinfo->topology[l].processor;
+ if (processor < 0) {
+ res = -EINVAL;
+ goto error;
+ }
+ }
+ else if (processor != cpuinfo->topology[l].processor) {
+ res = -EINVAL;
+ goto error;
+ }
+ cpuinfo->topology[l].logical = l;
+ cpuinfo->topology[l].thread = thread;
+ cpuinfo->topology[l].core = core_id[processor];
+ thread++;
+ }
+ }
+ core_id[processor]++;
+ break;
+ }
+ default:
+ /*
+ * We have reached the end of the relationships
+ * that we (currently) are interested in...
+ */
+ goto relationships_done;
+ }
+ }
+
+ relationships_done:
+
+ /*
+ * There may be unused entries; remove them...
+ */
+ for (rix = wix = 0; rix < cpuinfo->topology_size; rix++) {
+ if (cpuinfo->topology[rix].logical >= 0) {
+ if (wix != rix)
+ cpuinfo->topology[wix] = cpuinfo->topology[rix];
+ wix++;
+ }
+ }
+
+ if (cpuinfo->topology_size != wix) {
+ erts_cpu_topology_t *new = cpuinfo->topology;
+ new = realloc(cpuinfo->topology,
+ sizeof(erts_cpu_topology_t)*wix);
+ if (!new) {
+ res = -ENOMEM;
+ goto error;
+ }
+ cpuinfo->topology = new;
+ cpuinfo->topology_size = wix;
+ }
+
+ res = wix;
+
+ adjust_processor_nodes(cpuinfo, nodes);
+
+ qsort(cpuinfo->topology,
+ cpuinfo->topology_size,
+ sizeof(erts_cpu_topology_t),
+ cpu_cmp);
+
+ if (res < cpuinfo->online)
+ res = -EINVAL;
+
+ error:
+
+ if (res <= 0) {
+ cpuinfo->topology_size = 0;
+ if (cpuinfo->topology) {
+ free(cpuinfo->topology);
+ cpuinfo->topology = NULL;
+ }
+ }
+
+ if (slpip)
+ free(slpip);
+ if (core_id)
+ free(core_id);
+
+ return res;
+}
+
+#elif defined(__FreeBSD__)
+
+/**
+ * FreeBSD topology detection is based on kern.sched.topology_spec XML as
+ * exposed by the ULE scheduler and described in SMP(4). It is available in
+ * 8.0 and higher.
+ *
+ * Threads are identified in this XML chunk with a THREAD flag. The function
+ * (simplistically) distinguishes cores and processors by the amount of cache
+ * they share (0 => processor, otherwise => core). Nodes are not identified
+ * (ULE doesn't handle NUMA yet, I believe).
+ */
+
+/**
+ * Recursively parse a topology_spec <group> tag.
+ */
+static
+const char* parse_topology_spec_group(erts_cpu_info_t *cpuinfo, const char* xml, int parentCacheLevel, int* processor_p, int* core_p, int* index_procs_p) {
+ int error = 0;
+ int cacheLevel = parentCacheLevel;
+ const char* next_group_start = strstr(xml + 1, "<group");
+ int is_thread_group = 0;
+ const char* next_cache_level;
+ const char* next_thread_flag;
+ const char* next_group_end;
+ const char* next_children;
+ const char* next_children_end;
+
+ /* parse the cache level */
+ next_cache_level = strstr(xml, "cache-level=\"");
+ if (next_cache_level && (next_group_start == NULL || next_cache_level < next_group_start)) {
+ sscanf(next_cache_level, "cache-level=\"%i\"", &cacheLevel);
+ }
+
+ /* parse the threads flag */
+ next_thread_flag = strstr(xml, "THREAD");
+ if (next_thread_flag && (next_group_start == NULL || next_thread_flag < next_group_start))
+ is_thread_group = 1;
+
+ /* Determine if it's a leaf with the position of the next children tag */
+ next_group_end = strstr(xml, "</group>");
+ next_children = strstr(xml, "<children>");
+ next_children_end = strstr(xml, "</children>");
+ if (next_children == NULL || next_group_end < next_children) {
+ do {
+ const char* next_cpu_start;
+ const char* next_cpu_cdata;
+ const char* next_cpu_end;
+ int cpu_str_size;
+ char* cpu_str;
+ char* cpu_crsr;
+ char* brkb;
+ int thread = 0;
+ int index_procs = *index_procs_p;
+
+ next_cpu_start = strstr(xml, "<cpu");
+ if (!next_cpu_start) {
+ error = 1;
+ break;
+ }
+ next_cpu_cdata = strstr(next_cpu_start, ">") + 1;
+ if (!next_cpu_cdata) {
+ error = 1;
+ break;
+ }
+ next_cpu_end = strstr(next_cpu_cdata, "</cpu>");
+ if (!next_cpu_end) {
+ error = 1;
+ break;
+ }
+ cpu_str_size = next_cpu_end - next_cpu_cdata;
+ cpu_str = (char*) malloc(cpu_str_size + 1);
+ memcpy(cpu_str, (const char*) next_cpu_cdata, cpu_str_size);
+ cpu_str[cpu_str_size] = 0;
+ for (cpu_crsr = strtok_r(cpu_str, " \t,", &brkb); cpu_crsr; cpu_crsr = strtok_r(NULL, " \t,", &brkb)) {
+ int cpu_id;
+ if (index_procs >= cpuinfo->configured) {
+ void* t = realloc(cpuinfo->topology, (sizeof(erts_cpu_topology_t) * (index_procs + 1)));
+ if (t) {
+ cpuinfo->topology = t;
+ } else {
+ error = 1;
+ break;
+ }
+ }
+ cpu_id = atoi(cpu_crsr);
+ cpuinfo->topology[index_procs].node = -1;
+ cpuinfo->topology[index_procs].processor = *processor_p;
+ cpuinfo->topology[index_procs].processor_node = -1;
+ cpuinfo->topology[index_procs].core = *core_p;
+ cpuinfo->topology[index_procs].thread = thread;
+ cpuinfo->topology[index_procs].logical = cpu_id;
+ if (is_thread_group) {
+ thread++;
+ } else {
+ *core_p = (*core_p)++;
+ }
+ index_procs++;
+ }
+ *index_procs_p = index_procs;
+ free(cpu_str);
+ } while (0);
+ xml = next_group_end;
+ } else {
+ while (next_group_start != NULL && next_group_start < next_children_end) {
+ xml = parse_topology_spec_group(cpuinfo, next_group_start, cacheLevel, processor_p, core_p, index_procs_p);
+ if (!xml)
+ break;
+ next_group_start = strstr(xml, "<group");
+ next_children_end = strstr(xml, "</children>");
+ }
+ }
+
+ if (cacheLevel == 0) {
+ *core_p = 0;
+ *processor_p = (*processor_p)++;
+ } else {
+ *core_p = (*core_p)++;
+ }
+
+ if (error)
+ xml = NULL;
+
+ return xml;
+}
+
+/**
+ * Parse the topology_spec. Return the number of CPUs or 0 if parsing failed.
+ */
+static
+int parse_topology_spec(erts_cpu_info_t *cpuinfo, const char* xml) {
+ int res = 1;
+ int index_procs = 0;
+ int core = 0;
+ int processor = 0;
+ xml = strstr(xml, "<groups");
+ if (!xml)
+ return -1;
+
+ xml += 7;
+ xml = strstr(xml, "<group");
+ while (xml) {
+ xml = parse_topology_spec_group(cpuinfo, xml, 0, &processor, &core, &index_procs);
+ if (!xml) {
+ res = 0;
+ break;
+ }
+ xml = strstr(xml, "<group");
+ }
+
+ if (res)
+ res = index_procs;
+
+ return res;
+}
+
+static int
+read_topology(erts_cpu_info_t *cpuinfo)
+{
+ int ix;
+ int res = 0;
+ size_t topology_spec_size = 0;
+ void* topology_spec = NULL;
+
+ errno = 0;
+
+ if (cpuinfo->configured < 1)
+ goto error;
+
+ cpuinfo->topology_size = cpuinfo->configured;
+ cpuinfo->topology = malloc(sizeof(erts_cpu_topology_t)
+ * cpuinfo->configured);
+ if (!cpuinfo->topology) {
+ res = -ENOMEM;
+ goto error;
+ }
+
+ for (ix = 0; ix < cpuinfo->configured; ix++) {
+ cpuinfo->topology[ix].node = -1;
+ cpuinfo->topology[ix].processor = -1;
+ cpuinfo->topology[ix].processor_node = -1;
+ cpuinfo->topology[ix].core = -1;
+ cpuinfo->topology[ix].thread = -1;
+ cpuinfo->topology[ix].logical = -1;
+ }
+
+ if (!sysctlbyname("kern.sched.topology_spec", NULL, &topology_spec_size, NULL, 0)) {
+ topology_spec = malloc(topology_spec_size);
+ if (!topology_spec) {
+ res = -ENOMEM;
+ goto error;
+ }
+
+ if (sysctlbyname("kern.sched.topology_spec", topology_spec, &topology_spec_size, NULL, 0)) {
+ goto error;
+ }
+
+ res = parse_topology_spec(cpuinfo, topology_spec);
+ if (!res || res < cpuinfo->online)
+ res = 0;
+ else {
+ cpuinfo->topology_size = res;
+
+ if (cpuinfo->topology_size != cpuinfo->configured) {
+ void *t = realloc(cpuinfo->topology, (sizeof(erts_cpu_topology_t)
+ * cpuinfo->topology_size));
+ if (t)
+ cpuinfo->topology = t;
+ }
+
+ adjust_processor_nodes(cpuinfo, 1);
+
+ qsort(cpuinfo->topology,
+ cpuinfo->topology_size,
+ sizeof(erts_cpu_topology_t),
+ cpu_cmp);
+ }
+ }
+
+error:
+
+ if (res == 0) {
+ cpuinfo->topology_size = 0;
+ if (cpuinfo->topology) {
+ free(cpuinfo->topology);
+ cpuinfo->topology = NULL;
+ }
+ if (errno)
+ res = -errno;
+ else
+ res = -EINVAL;
+ }
+
+ if (topology_spec)
+ free(topology_spec);
+
+ return res;
+}
+
#else
static int
@@ -1016,9 +1650,9 @@ read_topology(erts_cpu_info_t *cpuinfo)
#if defined(__WIN32__)
int
-erts_get_last_win_errno(void)
+erts_map_win_error_to_errno(DWORD win_error)
{
- switch (GetLastError()) {
+ switch (win_error) {
case ERROR_INVALID_FUNCTION: return EINVAL; /* 1 */
case ERROR_FILE_NOT_FOUND: return ENOENT; /* 2 */
case ERROR_PATH_NOT_FOUND: return ENOENT; /* 3 */
@@ -1099,4 +1733,11 @@ erts_get_last_win_errno(void)
}
}
+int
+erts_get_last_win_errno(void)
+{
+ return erts_map_win_error_to_errno(GetLastError());
+}
+
+
#endif
diff --git a/erts/lib_src/common/ethr_mutex.c b/erts/lib_src/common/ethr_mutex.c
index f918bba81d..78323b62a3 100644
--- a/erts/lib_src/common/ethr_mutex.c
+++ b/erts/lib_src/common/ethr_mutex.c
@@ -35,7 +35,7 @@
#define ETHR_SPIN_WITH_WAITERS 1
-#define ETHR_MTX_MAX_FLGS_SPIN 1000
+#define ETHR_MTX_MAX_FLGS_SPIN 10
#ifdef ETHR_USE_OWN_RWMTX_IMPL__
static int default_rwmtx_main_spincount;
@@ -90,7 +90,7 @@ ethr_mutex_lib_init(int cpu_conf)
no_spin = cpu_conf == 1;
#ifdef ETHR_USE_OWN_MTX_IMPL__
- default_mtx_main_spincount = ETHR_MTX_DEFAULT_MAIN_SPINCOUNT;
+ default_mtx_main_spincount = ETHR_MTX_DEFAULT_MAIN_SPINCOUNT_BASE;
default_mtx_aux_spincount = ETHR_MTX_DEFAULT_AUX_SPINCOUNT;
default_cnd_main_spincount = ETHR_CND_DEFAULT_MAIN_SPINCOUNT;
default_cnd_aux_spincount = ETHR_CND_DEFAULT_AUX_SPINCOUNT;
@@ -98,7 +98,7 @@ ethr_mutex_lib_init(int cpu_conf)
#ifdef ETHR_USE_OWN_RWMTX_IMPL__
- default_rwmtx_main_spincount = ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT;
+ default_rwmtx_main_spincount = ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT_BASE;
default_rwmtx_aux_spincount = ETHR_RWMTX_DEFAULT_AUX_SPINCOUNT;
#else
@@ -146,7 +146,21 @@ static int main_threads_array_size = 0;
int
ethr_mutex_lib_late_init(int no_reader_groups, int no_main_threads)
{
+
+#ifdef ETHR_USE_OWN_MTX_IMPL__
+ default_mtx_main_spincount += (no_main_threads
+ * ETHR_MTX_DEFAULT_MAIN_SPINCOUNT_INC);
+ if (default_mtx_main_spincount > ETHR_MTX_DEFAULT_MAIN_SPINCOUNT_MAX)
+ default_mtx_main_spincount = ETHR_MTX_DEFAULT_MAIN_SPINCOUNT_MAX;
+#endif
+
#ifdef ETHR_USE_OWN_RWMTX_IMPL__
+
+ default_rwmtx_main_spincount += (no_main_threads
+ * ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT_INC);
+ if (default_rwmtx_main_spincount > ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT_MAX)
+ default_rwmtx_main_spincount = ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT_MAX;
+
reader_groups_array_size = (no_reader_groups <= 1
? 1
: no_reader_groups + 1);
@@ -593,24 +607,31 @@ initial_spincount(struct ethr_mutex_base_ *mtxb)
static ETHR_INLINE int
update_spincount(struct ethr_mutex_base_ *mtxb,
ethr_ts_event *tse,
- int *start_scnt,
+ int *scnt_state,
int *scnt)
{
- int sscnt = *start_scnt;
- if (sscnt < 0) {
- *scnt = ((tse->iflgs & ETHR_TS_EV_MAIN_THR)
- ? mtxb->main_scnt
- : mtxb->aux_scnt);
- *scnt -= ETHR_MTX_MAX_FLGS_SPIN;
+ int state = *scnt_state;
+ if (state <= 0) {
+ /* Here state is max spincount to do on event negated */
+ *scnt = -state;
}
else {
+ /* Here state is initial spincount made on flags */
*scnt = ((tse->iflgs & ETHR_TS_EV_MAIN_THR)
? mtxb->main_scnt
: mtxb->aux_scnt);
- *scnt -= sscnt;
- if (*scnt > 0 && sscnt < ETHR_MTX_MAX_FLGS_SPIN) {
- *scnt = ETHR_MTX_MAX_FLGS_SPIN - sscnt;
- *start_scnt = -1;
+ if (*scnt <= state)
+ *scnt = 0;
+ else {
+ if (*scnt <= ETHR_MTX_MAX_FLGS_SPIN)
+ *scnt_state = 0; /* No spin on event */
+ else {
+ /* Spin on event after... */
+ *scnt_state = -1*(*scnt - ETHR_MTX_MAX_FLGS_SPIN);
+ /* ... we have spun on flags */
+ *scnt = ETHR_MTX_MAX_FLGS_SPIN;
+ }
+ *scnt -= state;
return 0;
}
}
@@ -619,8 +640,7 @@ update_spincount(struct ethr_mutex_base_ *mtxb,
int check_readers_array(ethr_rwmutex *rwmtx,
int start_rix,
- int length,
- int pre_check);
+ int length);
static ETHR_INLINE void
write_lock_wait(struct ethr_mutex_base_ *mtxb,
@@ -666,8 +686,7 @@ write_lock_wait(struct ethr_mutex_base_ *mtxb,
}
res = check_readers_array(rwmtx,
freq_read_start_ix,
- freq_read_size,
- 1);
+ freq_read_size);
scnt--;
if (res == 0) {
act = ethr_atomic_read(&mtxb->flgs);
@@ -708,7 +727,6 @@ write_lock_wait(struct ethr_mutex_base_ *mtxb,
act = ethr_atomic_read(&mtxb->flgs);
scnt--;
}
- ETHR_ASSERT(scnt >= 0);
exp = act;
@@ -985,7 +1003,6 @@ enqueue_mtx(ethr_mutex *mtx, ethr_ts_event *tse_start, ethr_ts_event *tse_end)
int
ethr_cond_init_opt(ethr_cond *cnd, ethr_cond_opt *opt)
{
- int res;
#if ETHR_XCHK
if (!cnd) {
ETHR_ASSERT(0);
@@ -1048,7 +1065,7 @@ ethr_cond_signal(ethr_cond *cnd)
ethr_ts_event *tse;
ETHR_ASSERT(!ethr_not_inited__);
- ETHR_ASSERT(!cnd);
+ ETHR_ASSERT(cnd);
ETHR_ASSERT(cnd->initialized == ETHR_COND_INITIALIZED);
ETHR_MTX_HARD_DEBUG_FENCE_CHK(cnd);
@@ -1085,11 +1102,10 @@ ethr_cond_signal(ethr_cond *cnd)
void
ethr_cond_broadcast(ethr_cond *cnd)
{
- int res;
int got_all;
ethr_ts_event *tse;
ETHR_ASSERT(!ethr_not_inited__);
- ETHR_ASSERT(!cnd);
+ ETHR_ASSERT(cnd);
ETHR_ASSERT(cnd->initialized == ETHR_COND_INITIALIZED);
ETHR_MTX_HARD_DEBUG_FENCE_CHK(cnd);
@@ -1153,14 +1169,13 @@ ethr_cond_wait(ethr_cond *cnd, ethr_mutex *mtx)
{
int woken;
int scnt;
- int res;
void *udata = NULL;
ethr_ts_event *tse;
ETHR_ASSERT(!ethr_not_inited__);
- ETHR_ASSERT(!cnd);
+ ETHR_ASSERT(cnd);
ETHR_ASSERT(cnd->initialized == ETHR_COND_INITIALIZED);
- ETHR_ASSERT(!mtx);
+ ETHR_ASSERT(mtx);
ETHR_ASSERT(mtx->initialized == ETHR_MUTEX_INITIALIZED);
tse = ethr_get_ts_event();
@@ -1466,17 +1481,11 @@ multiple_w_waiters(ethr_rwmutex *rwmtx)
int check_readers_array(ethr_rwmutex *rwmtx,
int start_rix,
- int length,
- int pre_check)
+ int length)
{
int ix = start_rix;
-#ifndef ETHR_READ_MEMORY_BARRIER_IS_FULL
- if (pre_check)
- ETHR_READ_MEMORY_BARRIER;
- else
-#endif
- ETHR_MEMORY_BARRIER;
+ ETHR_MEMORY_BARRIER;
do {
long act = rwmutex_freqread_rdrs_read(rwmtx, ix);
@@ -1559,7 +1568,7 @@ rwmutex_try_complete_runlock(ethr_rwmutex *rwmtx,
ethr_leave_ts_event(tse_tmp);
if (check_before_try) {
- res = check_readers_array(rwmtx, six, length, 1);
+ res = check_readers_array(rwmtx, six, length);
if (res == EBUSY)
return try_write_lock ? EBUSY : 0;
}
@@ -1597,7 +1606,7 @@ rwmutex_try_complete_runlock(ethr_rwmutex *rwmtx,
}
}
- res = check_readers_array(rwmtx, six, length, 0);
+ res = check_readers_array(rwmtx, six, length);
if (res == EBUSY) {
act = ethr_atomic_dec_read(&rwmtx->mtxb.flgs);
if (act & ETHR_RWMTX_R_MASK__)
@@ -1691,7 +1700,7 @@ rwmutex_normal_rlock_wait(ethr_rwmutex *rwmtx,
#endif
while (act & (ETHR_RWMTX_W_FLG__|ETHR_RWMTX_W_WAIT_FLG__)) {
- if (scnt == 0) {
+ if (scnt >= 0) {
tse = ethr_get_ts_event();
if (update_spincount(&rwmtx->mtxb, tse, &start_scnt, &scnt)) {
event_wait(&rwmtx->mtxb, tse, scnt,
@@ -1708,7 +1717,6 @@ rwmutex_normal_rlock_wait(ethr_rwmutex *rwmtx,
scnt--;
}
exp = act;
- ETHR_ASSERT(scnt >= 0);
#ifdef ETHR_RLOCK_WITH_INC_DEC
act = ethr_atomic_inc_read(&rwmtx->mtxb.flgs);
@@ -1749,7 +1757,7 @@ rwmutex_freqread_rlock_wait(ethr_rwmutex *rwmtx,
act = ethr_atomic_read(&rwmtx->mtxb.flgs);
while (act & ~(ETHR_RWMTX_R_FLG__|ETHR_RWMTX_R_WAIT_FLG__)) {
- if (scnt == 0) {
+ if (scnt >= 0) {
if (update_spincount(&rwmtx->mtxb, tse, &start_scnt, &scnt)) {
event_wait(&rwmtx->mtxb, tse, scnt,
ETHR_RWMTX_R_WAIT_FLG__, 1, 1);
@@ -1765,8 +1773,6 @@ rwmutex_freqread_rlock_wait(ethr_rwmutex *rwmtx,
scnt--;
}
- ETHR_ASSERT(scnt >= 0);
-
rwmutex_freqread_rdrs_inc(rwmtx, tse);
ETHR_MEMORY_BARRIER;
diff --git a/erts/preloaded/ebin/erl_prim_loader.beam b/erts/preloaded/ebin/erl_prim_loader.beam
index 7b824f1ab4..222809e662 100644
--- a/erts/preloaded/ebin/erl_prim_loader.beam
+++ b/erts/preloaded/ebin/erl_prim_loader.beam
Binary files differ
diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam
index 3cab91b722..65c7369b76 100644
--- a/erts/preloaded/ebin/erlang.beam
+++ b/erts/preloaded/ebin/erlang.beam
Binary files differ
diff --git a/erts/preloaded/ebin/init.beam b/erts/preloaded/ebin/init.beam
index 9f88ddd51e..c8d3b78b35 100644
--- a/erts/preloaded/ebin/init.beam
+++ b/erts/preloaded/ebin/init.beam
Binary files differ
diff --git a/erts/preloaded/ebin/otp_ring0.beam b/erts/preloaded/ebin/otp_ring0.beam
index 4c9cc9675b..abf17bcb0e 100644
--- a/erts/preloaded/ebin/otp_ring0.beam
+++ b/erts/preloaded/ebin/otp_ring0.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_file.beam b/erts/preloaded/ebin/prim_file.beam
index 9a4904b6a1..a3f300268f 100644
--- a/erts/preloaded/ebin/prim_file.beam
+++ b/erts/preloaded/ebin/prim_file.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_inet.beam b/erts/preloaded/ebin/prim_inet.beam
index ac336c1b2d..3f53f35273 100644
--- a/erts/preloaded/ebin/prim_inet.beam
+++ b/erts/preloaded/ebin/prim_inet.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_zip.beam b/erts/preloaded/ebin/prim_zip.beam
index c57d37725e..0fe38a1fb2 100644
--- a/erts/preloaded/ebin/prim_zip.beam
+++ b/erts/preloaded/ebin/prim_zip.beam
Binary files differ
diff --git a/erts/preloaded/ebin/zlib.beam b/erts/preloaded/ebin/zlib.beam
index 6b14d3fd66..7108bf44d0 100644
--- a/erts/preloaded/ebin/zlib.beam
+++ b/erts/preloaded/ebin/zlib.beam
Binary files differ
diff --git a/erts/preloaded/src/Makefile b/erts/preloaded/src/Makefile
index 785ad531f3..145638802f 100644
--- a/erts/preloaded/src/Makefile
+++ b/erts/preloaded/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2009. All Rights Reserved.
+# Copyright Ericsson AB 2008-2010. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -20,8 +20,7 @@
# be used when the preloaded modules actually are to be updated (i.e. the
# beam files are to be recompiled, which is normally not done).
# The beam files are placed in the current directory and should be copied
-# to the ../ebin directory by using the commit target (only works in
-# clearcase).
+# to the ../ebin directory by using the copy target.
include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
@@ -62,26 +61,9 @@ debug opt: $(TARGET_FILES)
clean:
rm -f $(TARGET_FILES)
-prepare:
- cleartool co -nc $(STATIC_EBIN)/*
- cleartool co -nc $(STATIC_EBIN)
-
copy:
- for x in *.beam; do\
- if test '!' -f $(STATIC_EBIN)/$$x; then\
- cleartool mkelem -nc $$x;\
- fi;\
- done
cp *.beam $(STATIC_EBIN)
-commit:
- cleartool ci -ident -nc $(STATIC_EBIN)/*.beam
- cleartool ci -ident -nc $(STATIC_EBIN)
-
-cancel:
- -cleartool unco -rm $(STATIC_EBIN)
- -cleartool unco -rm $(STATIC_EBIN)/*.beam
-
include $(ERL_TOP)/make/otp_release_targets.mk
diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl
index 3b98b9cddc..3ab9a1cd6d 100644
--- a/erts/preloaded/src/init.erl
+++ b/erts/preloaded/src/init.erl
@@ -51,6 +51,9 @@
get_status/0,boot/1,get_arguments/0,get_plain_arguments/0,
get_argument/1,script_id/0]).
+%% for the on_load functionality; not for general use
+-export([run_on_load_handlers/0]).
+
%% internal exports
-export([fetch_loaded/0,ensure_loaded/1,make_permanent/2,
notify_when_started/1,wait_until_started/0,
@@ -308,24 +311,6 @@ boot_loop(BootPid, State) ->
{stop,Reason} ->
stop(Reason,State);
{From,fetch_loaded} -> %% Fetch and reset initially loaded modules.
- case whereis(?ON_LOAD_HANDLER) of
- undefined ->
- %% There is no on_load handler process,
- %% probably because init:restart/0 has been
- %% called and it is not the first time we
- %% pass through here.
- ok;
- Pid when is_pid(Pid) ->
- Pid ! run_on_load,
- receive
- {'EXIT',Pid,on_load_done} ->
- ok;
- {'EXIT',Pid,Res} ->
- %% Failure to run an on_load handler.
- %% This is fatal during start-up.
- exit(Res)
- end
- end,
From ! {init,State#state.loaded},
garb_boot_loop(BootPid,State#state{loaded = []});
{From,{ensure_loaded,Module}} ->
@@ -736,6 +721,7 @@ do_boot(Init,Flags,Start) ->
BootList = get_boot(BootFile,Root),
LoadMode = b2a(get_flag('-mode',Flags,false)),
Deb = b2a(get_flag('-init_debug',Flags,false)),
+ catch ?ON_LOAD_HANDLER ! {init_debug_flag,Deb},
BootVars = get_flag_args('-boot_var',Flags),
ParallelLoad =
(Pgm =:= "efile") and (erlang:system_info(thread_pool_size) > 0),
@@ -1335,23 +1321,44 @@ archive_extension() ->
%%% Support for handling of on_load functions.
%%%
+run_on_load_handlers() ->
+ Ref = monitor(process, ?ON_LOAD_HANDLER),
+ catch ?ON_LOAD_HANDLER ! run_on_load,
+ receive
+ {'DOWN',Ref,process,_,noproc} ->
+ %% There is no on_load handler process,
+ %% probably because init:restart/0 has been
+ %% called and it is not the first time we
+ %% pass through here.
+ ok;
+ {'DOWN',Ref,process,_,on_load_done} ->
+ ok;
+ {'DOWN',Ref,process,_,Res} ->
+ %% Failure to run an on_load handler.
+ %% This is fatal during start-up.
+ exit(Res)
+ end.
+
start_on_load_handler_process() ->
register(?ON_LOAD_HANDLER,
- spawn_link(fun on_load_handler_init/0)).
+ spawn(fun on_load_handler_init/0)).
on_load_handler_init() ->
- on_load_loop([]).
+ on_load_loop([], false).
-on_load_loop(Mods) ->
+on_load_loop(Mods, Debug0) ->
receive
+ {init_debug_flag,Debug} ->
+ on_load_loop(Mods, Debug);
{loaded,Mod} ->
- on_load_loop([Mod|Mods]);
+ on_load_loop([Mod|Mods], Debug0);
run_on_load ->
- run_on_load_handlers(Mods),
+ run_on_load_handlers(Mods, Debug0),
exit(on_load_done)
end.
-run_on_load_handlers([M|Ms]) ->
+run_on_load_handlers([M|Ms], Debug) ->
+ debug(Debug, {running_on_load_handler,M}),
Fun = fun() ->
Res = erlang:call_on_load_function(M),
exit(Res)
@@ -1363,9 +1370,12 @@ run_on_load_handlers([M|Ms]) ->
erlang:finish_after_on_load(M, Keep),
case Keep of
false ->
- exit({on_load_function_failed,M});
+ Error = {on_load_function_failed,M},
+ debug(Debug, Error),
+ exit(Error);
true ->
- run_on_load_handlers(Ms)
+ debug(Debug, {on_load_handler_returned_ok,M}),
+ run_on_load_handlers(Ms, Debug)
end
end;
-run_on_load_handlers([]) -> ok.
+run_on_load_handlers([], _) -> ok.
diff --git a/erts/preloaded/src/prim_inet.erl b/erts/preloaded/src/prim_inet.erl
index 0feb591efb..446656e45f 100644
--- a/erts/preloaded/src/prim_inet.erl
+++ b/erts/preloaded/src/prim_inet.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -37,7 +37,7 @@
-export([setopt/3, setopts/2, getopt/2, getopts/2, is_sockopt_val/2]).
-export([chgopt/3, chgopts/2]).
-export([getstat/2, getfd/1, getindex/1, getstatus/1, gettype/1,
- getiflist/1, ifget/3, ifset/3,
+ getifaddrs/1, getiflist/1, ifget/3, ifset/3,
gethostname/1]).
-export([getservbyname/3, getservbyport/3]).
-export([peername/1, setpeername/2]).
@@ -216,9 +216,10 @@ bindx(S, AddFlag, Addrs) ->
sctp ->
%% Really multi-homed "bindx". Stringified args:
%% [AddFlag, (Port, IP)+]:
- Args = ?int8(AddFlag) ++
- lists:concat([?int16(Port)++ip_to_bytes(IP) ||
- {IP, Port} <- Addrs]),
+ Args =
+ [?int8(AddFlag)|
+ [[?int16(Port)|ip_to_bytes(IP)] ||
+ {IP, Port} <- Addrs]],
case ctl_cmd(S, ?SCTP_REQ_BINDX, Args) of
{ok,_} -> {ok, S};
Error -> Error
@@ -623,7 +624,7 @@ chgopt(S, Opt, Value) when is_port(S) ->
chgopts(S, [{Opt,Value}]).
chgopts(S, Opts) when is_port(S), is_list(Opts) ->
- case inet:getopts(S, need_template(Opts)) of
+ case getopts(S, need_template(Opts)) of
{ok,Templates} ->
try merge_options(Opts, Templates) of
NewOpts ->
@@ -636,7 +637,94 @@ chgopts(S, Opts) when is_port(S), is_list(Opts) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
-%% IFLIST(insock()) -> {ok,IfNameList} | {error, Reason}
+%% getifaddrs(insock()) -> {ok,IfAddrsList} | {error, Reason}
+%%
+%% IfAddrsList = [{Name,[Opts]}]
+%% Name = string()
+%% Opts = {flags,[Flag]} | {addr,Addr} | {netmask,Addr} | {broadaddr,Addr}
+%% | {dstaddr,Addr} | {hwaddr,HwAddr} | {mtu,integer()}
+%% Flag = up | broadcast | loopback | running | multicast
+%% Addr = ipv4addr() | ipv6addr()
+%% HwAddr = ethernet_addr()
+%%
+%% get interface name and addresses list
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+getifaddrs(S) when is_port(S) ->
+ case ctl_cmd(S, ?INET_REQ_GETIFADDRS, []) of
+ {ok, Data} ->
+ {ok, comp_ifaddrs(build_ifaddrs(Data), ktree_empty())};
+ {error,enotsup} ->
+ case getiflist(S) of
+ {ok, IFs} ->
+ {ok, getifaddrs_ifget(S, IFs)};
+ Err1 -> Err1
+ end;
+ Err2 -> Err2
+ end.
+
+%% Restructure interface properties per interface and remove duplicates
+
+comp_ifaddrs([{If,Opts}|IfOpts], T) ->
+ case ktree_is_defined(If, T) of
+ true ->
+ OptSet = comp_ifaddrs_add(ktree_get(If, T), Opts),
+ comp_ifaddrs(IfOpts, ktree_update(If, OptSet, T));
+ false ->
+ OptSet = comp_ifaddrs_add(ktree_empty(), Opts),
+ comp_ifaddrs(IfOpts, ktree_insert(If, OptSet, T))
+ end;
+comp_ifaddrs([], T) ->
+ [{If,ktree_keys(ktree_get(If, T))} || If <- ktree_keys(T)].
+
+comp_ifaddrs_add(OptSet, [Opt|Opts]) ->
+ case ktree_is_defined(Opt, OptSet) of
+ true
+ when element(1, Opt) =:= flags;
+ element(1, Opt) =:= hwaddr ->
+ comp_ifaddrs_add(OptSet, Opts);
+ _ ->
+ comp_ifaddrs_add(ktree_insert(Opt, undefined, OptSet), Opts)
+ end;
+comp_ifaddrs_add(OptSet, []) -> OptSet.
+
+%% Legacy emulation of getifaddrs
+
+getifaddrs_ifget(_, []) -> [];
+getifaddrs_ifget(S, [IF|IFs]) ->
+ case ifget(S, IF, [flags]) of
+ {ok,[{flags,Flags}]=FlagsVals} ->
+ BroadOpts =
+ case member(broadcast, Flags) of
+ true ->
+ [broadaddr,hwaddr];
+ false ->
+ [hwaddr]
+ end,
+ P2POpts =
+ case member(pointtopoint, Flags) of
+ true ->
+ [dstaddr|BroadOpts];
+ false ->
+ BroadOpts
+ end,
+ getifaddrs_ifget(S, IFs, IF, FlagsVals, [addr,netmask|P2POpts]);
+ _ ->
+ getifaddrs_ifget(S, IFs, IF, [], [addr,netmask,hwaddr])
+ end.
+
+getifaddrs_ifget(S, IFs, IF, FlagsVals, Opts) ->
+ OptVals =
+ case ifget(S, IF, Opts) of
+ {ok,OVs} -> OVs;
+ _ -> []
+ end,
+ [{IF,FlagsVals++OptVals}|getifaddrs_ifget(S, IFs)].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% getiflist(insock()) -> {ok,IfNameList} | {error, Reason}
%%
%% get interface name list
%%
@@ -1206,7 +1294,7 @@ type_opt_1(sctp_default_send_param) ->
timetolive = [uint32,0],
tsn = [],
cumtsn = [],
- assoc_id = [sctp_assoc_id,0]}}];
+ assoc_id = [[sctp_assoc_id,0]]}}];
%% for SCTP_OPT_EVENTS
type_opt_1(sctp_events) ->
[{record,#sctp_event_subscribe{
@@ -1325,6 +1413,19 @@ type_value_2({enum,List}, Enum) ->
{value,_} -> true;
false -> false
end;
+type_value_2(sockaddr, Addr) ->
+ case Addr of
+ any -> true;
+ loopback -> true;
+ {A,B,C,D} when ?ip(A,B,C,D) -> true;
+ {A,B,C,D,E,F,G,H} when ?ip6(A,B,C,D,E,F,G,H) -> true;
+ _ -> false
+ end;
+type_value_2(linkaddr, Addr) when is_list(Addr) ->
+ case len(Addr, 32768) of
+ undefined -> false;
+ _ -> true
+ end;
type_value_2({bitenumlist,List}, EnumList) ->
case enum_vals(EnumList, List) of
Ls when is_list(Ls) -> true;
@@ -1413,14 +1514,21 @@ enc_value_2(addr, {any,Port}) ->
[?INET_AF_ANY|?int16(Port)];
enc_value_2(addr, {loopback,Port}) ->
[?INET_AF_LOOPBACK|?int16(Port)];
-enc_value_2(addr, {IP,Port}) ->
- case tuple_size(IP) of
- 4 ->
- [?INET_AF_INET,?int16(Port)|ip4_to_bytes(IP)];
- 8 ->
- [?INET_AF_INET6,?int16(Port)|ip6_to_bytes(IP)]
- end;
+enc_value_2(addr, {IP,Port}) when tuple_size(IP) =:= 4 ->
+ [?INET_AF_INET,?int16(Port)|ip4_to_bytes(IP)];
+enc_value_2(addr, {IP,Port}) when tuple_size(IP) =:= 8 ->
+ [?INET_AF_INET6,?int16(Port)|ip6_to_bytes(IP)];
enc_value_2(ether, [X1,X2,X3,X4,X5,X6]) -> [X1,X2,X3,X4,X5,X6];
+enc_value_2(sockaddr, any) ->
+ [?INET_AF_ANY];
+enc_value_2(sockaddr, loopback) ->
+ [?INET_AF_LOOPBACK];
+enc_value_2(sockaddr, IP) when tuple_size(IP) =:= 4 ->
+ [?INET_AF_INET|ip4_to_bytes(IP)];
+enc_value_2(sockaddr, IP) when tuple_size(IP) =:= 8 ->
+ [?INET_AF_INET6|ip6_to_bytes(IP)];
+enc_value_2(linkaddr, Linkaddr) ->
+ [?int16(length(Linkaddr)),Linkaddr];
enc_value_2(sctp_assoc_id, Val) -> ?int32(Val);
%% enc_value_2(sctp_assoc_id, Bin) -> [byte_size(Bin),Bin];
enc_value_2({enum,List}, Enum) ->
@@ -1465,6 +1573,10 @@ dec_value(time, [X3,X2,X1,X0|T]) ->
end;
dec_value(ip, [A,B,C,D|T]) -> {{A,B,C,D}, T};
dec_value(ether,[X1,X2,X3,X4,X5,X6|T]) -> {[X1,X2,X3,X4,X5,X6],T};
+dec_value(sockaddr, [X|T]) ->
+ get_ip(X, T);
+dec_value(linkaddr, [X1,X0|T]) ->
+ split(?i16(X1,X0), T);
dec_value({enum,List}, [X3,X2,X1,X0|T]) ->
Val = ?i32(X3,X2,X1,X0),
case enum_name(Val, List) of
@@ -1480,7 +1592,7 @@ dec_value({bitenumlist,List}, [X3,X2,X1,X0|T]) ->
%% {enum_names(Val, List), T};
dec_value(binary,[L0,L1,L2,L3|List]) ->
Len = ?i32(L0,L1,L2,L3),
- {X,T}=lists:split(Len,List),
+ {X,T}=split(Len,List),
{list_to_binary(X),T};
dec_value(Types, List) when is_tuple(Types) ->
{L,T} = dec_value_tuple(Types, List, 1, []),
@@ -1495,7 +1607,7 @@ dec_value_tuple(Types, List, N, Acc)
{Term,Tail} = dec_value(element(N, Types), List),
dec_value_tuple(Types, Tail, N+1, [Term|Acc]);
dec_value_tuple(_, List, _, Acc) ->
- {lists:reverse(Acc),List}.
+ {rev(Acc),List}.
borlist([V|Vs], Value) ->
borlist(Vs, V bor Value);
@@ -1702,11 +1814,11 @@ merge_fields(_, _, _) -> [].
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-type_ifopt(addr) -> ip;
-type_ifopt(broadaddr) -> ip;
-type_ifopt(dstaddr) -> ip;
+type_ifopt(addr) -> sockaddr;
+type_ifopt(broadaddr) -> sockaddr;
+type_ifopt(dstaddr) -> sockaddr;
type_ifopt(mtu) -> int;
-type_ifopt(netmask) -> ip;
+type_ifopt(netmask) -> sockaddr;
type_ifopt(flags) ->
{bitenumlist,
[{up, ?INET_IFF_UP},
@@ -1718,7 +1830,7 @@ type_ifopt(flags) ->
{no_pointtopoint, ?INET_IFF_NPOINTTOPOINT},
{running, ?INET_IFF_RUNNING},
{multicast, ?INET_IFF_MULTICAST}]};
-type_ifopt(hwaddr) -> ether;
+type_ifopt(hwaddr) -> linkaddr;
type_ifopt(Opt) when is_atom(Opt) -> undefined.
enc_ifopt(addr) -> ?INET_IFOPT_ADDR;
@@ -1903,6 +2015,30 @@ encode_ifname(Name) ->
if N > 255 -> {error, einval};
true -> {ok,[N | Name]}
end.
+
+build_ifaddrs(Cs) ->
+ build_ifaddrs(Cs, []).
+%%
+build_ifaddrs([], []) ->
+ [];
+build_ifaddrs([0|Cs], Acc) ->
+ Name = utf8_to_characters(rev(Acc)),
+ {Opts,Rest} = build_ifaddrs_opts(Cs, []),
+ [{Name,Opts}|build_ifaddrs(Rest)];
+build_ifaddrs([C|Cs], Acc) ->
+ build_ifaddrs(Cs, [C|Acc]).
+
+build_ifaddrs_opts([0|Cs], Acc) ->
+ {rev(Acc),Cs};
+build_ifaddrs_opts([C|Cs]=CCs, Acc) ->
+ case dec_ifopt(C) of
+ undefined ->
+ erlang:error(badarg, [CCs,Acc]);
+ Opt ->
+ Type = type_ifopt(Opt),
+ {Val,Rest} = dec_value(Type, Cs),
+ build_ifaddrs_opts(Rest, [{Opt,Val}|Acc])
+ end.
build_iflist(Cs) ->
build_iflist(Cs, [], []).
@@ -1927,6 +2063,80 @@ rev(L) -> rev(L,[]).
rev([C|L],Acc) -> rev(L,[C|Acc]);
rev([],Acc) -> Acc.
+split(N, L) -> split(N, L, []).
+split(0, L, R) when is_list(L) -> {rev(R),L};
+split(N, [H|T], R) when is_integer(N), N > 0 -> split(N-1, T, [H|R]).
+
+len(L, N) -> len(L, N, 0).
+len([], N, C) when is_integer(N), N >= 0 -> C;
+len(L, 0, _) when is_list(L) -> undefined;
+len([_|L], N, C) when is_integer(N), N >= 0 -> len(L, N-1, C+1).
+
+member(X, [X|_]) -> true;
+member(X, [_|Xs]) -> member(X, Xs);
+member(_, []) -> false.
+
+
+
+%% Lookup tree that keeps key insert order
+
+ktree_empty() -> {[],tree()}.
+ktree_is_defined(Key, {_,T}) -> tree(T, Key, is_defined).
+ktree_get(Key, {_,T}) -> tree(T, Key, get).
+ktree_insert(Key, V, {Keys,T}) -> {[Key|Keys],tree(T, Key, {insert,V})}.
+ktree_update(Key, V, {Keys,T}) -> {Keys,tree(T, Key, {update,V})}.
+ktree_keys({Keys,_}) -> rev(Keys).
+
+%% Simple lookup tree. Hash the key to get statistical balance.
+%% Key is matched equal, not compared equal.
+
+tree() -> nil.
+tree(T, Key, Op) -> tree(T, Key, Op, erlang:phash2(Key)).
+
+tree(nil, _, is_defined, _) -> false;
+tree(nil, K, {insert,V}, _) -> {K,V,nil,nil};
+tree({K,_,_,_}, K, is_defined, _) -> true;
+tree({K,V,_,_}, K, get, _) -> V;
+tree({K,_,L,R}, K, {update,V}, _) -> {K,V,L,R};
+tree({K0,V0,L,R}, K, Op, H) ->
+ H0 = erlang:phash2(K0),
+ if H0 < H; H0 =:= H, K0 < K ->
+ if is_tuple(Op) ->
+ {K0,V0,tree(L, K, Op, H),R};
+ true ->
+ tree(L, K, Op, H)
+ end;
+ true ->
+ if is_tuple(Op) ->
+ {K0,V0,L,tree(R, K, Op, H)};
+ true ->
+ tree(R, K, Op, H)
+ end
+ end.
+
+
+
+utf8_to_characters([]) -> [];
+utf8_to_characters([B|Bs]=Arg) when (B band 16#FF) =:= B ->
+ if 16#F8 =< B ->
+ erlang:error(badarg, [Arg]);
+ 16#F0 =< B ->
+ utf8_to_characters(Bs, B band 16#07, 3);
+ 16#E0 =< B ->
+ utf8_to_characters(Bs, B band 16#0F, 2);
+ 16#C0 =< B ->
+ utf8_to_characters(Bs, B band 16#1F, 1);
+ 16#80 =< B ->
+ erlang:error(badarg, [Arg]);
+ true ->
+ [B|utf8_to_characters(Bs)]
+ end.
+%%
+utf8_to_characters(Bs, U, 0) ->
+ [U|utf8_to_characters(Bs)];
+utf8_to_characters([B|Bs], U, N) when ((B band 16#3F) bor 16#80) =:= B ->
+ utf8_to_characters(Bs, (U bsl 6) bor (B band 16#3F), N-1).
+
ip_to_bytes(IP) when tuple_size(IP) =:= 4 -> ip4_to_bytes(IP);
ip_to_bytes(IP) when tuple_size(IP) =:= 8 -> ip6_to_bytes(IP).
diff --git a/erts/test/Makefile b/erts/test/Makefile
index 796403e182..94458da019 100644
--- a/erts/test/Makefile
+++ b/erts/test/Makefile
@@ -28,6 +28,7 @@ EBIN = .
# ----------------------------------------------------
MODULES= \
+ autoimport_SUITE \
erlc_SUITE \
install_SUITE \
nt_SUITE \
@@ -38,12 +39,14 @@ MODULES= \
erlexec_SUITE \
z_SUITE
+ERL_XML = $(ERL_TOP)/erts/doc/src/erlang.xml
+ERL_XML_TARGET = autoimport_SUITE_data/erlang.xml
ERL_FILES= $(MODULES:%=%.erl)
TARGET_FILES = $(MODULES:%=$(EBIN)/%.$(EMULATOR))
-EXTRA_FILES = install_SUITE_data/install_bin
+EXTRA_FILES = install_SUITE_data/install_bin $(ERL_XML_TARGET)
# ----------------------------------------------------
# Release directory specification
@@ -65,6 +68,10 @@ install_SUITE_data/install_bin: ../../make/install_bin
rm -f $@
cp -p $< $@
+$(ERL_XML_TARGET): $(ERL_XML)
+ rm -f $@
+ cp -p $< $@
+
clean:
rm -f $(TARGET_FILES) $(EXTRA_FILES)
rm -f core *~
diff --git a/erts/test/autoimport_SUITE.erl b/erts/test/autoimport_SUITE.erl
new file mode 100644
index 0000000000..2430dac78d
--- /dev/null
+++ b/erts/test/autoimport_SUITE.erl
@@ -0,0 +1,163 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%% Purpose: Test erlang.xml re autoimports
+-module(autoimport_SUITE).
+
+-include_lib("test_server/include/test_server.hrl").
+-export([all/1,init_per_testcase/2,fin_per_testcase/2,autoimports/1]).
+-define(TEST_TIMEOUT, ?t:seconds(180)).
+
+all(suite) -> [autoimports].
+
+init_per_testcase(_Func, Config) ->
+ Dog = test_server:timetrap(?TEST_TIMEOUT),
+ [{watchdog, Dog} | Config].
+
+fin_per_testcase(_Func, Config) ->
+ Dog = ?config(watchdog, Config),
+ catch test_server:timetrap_cancel(Dog),
+ ok.
+
+
+autoimports(suite) ->
+ [];
+autoimports(doc) ->
+ ["Check that erlang.xml documents autoimports correctly"];
+autoimports(Config) when is_list(Config) ->
+ ?line XML = filename:join([?config(data_dir,Config),"erlang.xml"]),
+ ?line case xml(XML) of
+ [] ->
+ ok;
+ List ->
+ lists:foreach(fun({[],F,A}) ->
+ io:format("erlang:~s/~p is wrongly "
+ "documented as ~s/~p~n",
+ [F,A,F,A]);
+ ({"erlang",F,A}) ->
+ io:format("~s/~p is wrongly "
+ "documented as "
+ "erlang:~s/~p~n",
+ [F,A,F,A])
+ end,List),
+ ?t:fail({wrong_autoimports,List})
+ end.
+
+%%
+%% Ugly chunk of code to heuristically analyze the erlang.xml
+%% documentation file. Don't view this as an example...
+%%
+
+xml(XMLFile) ->
+ {ok,File} = file:open(XMLFile,[read]),
+ DocData = xloop(file:read_line(File),File),
+ file:close(File),
+ analyze(DocData).
+
+xloop({ok,Line},File) ->
+ case re:run(Line,"\\<name\\>",[{capture,none}]) of
+ nomatch ->
+ xloop(file:read_line(File),File);
+ match ->
+ X = re:replace(Line,"\\).*",")",[{return,list}]),
+ Y = re:replace(X,".*\\>","",[{return,list}]),
+ Mod = get_module(Y),
+ Rest1 = fstrip(Mod++":",Y),
+ Func = get_function(Rest1),
+ Rest2 = fstrip(Func++"(", Rest1),
+ Argc = count_args(Rest2,1,0,false),
+ [{Mod,Func,Argc} |
+ xloop(file:read_line(File),File)]
+ end;
+xloop(_,_) ->
+ [].
+
+analyze([{[],Func,Arity}|T]) ->
+ case erl_internal:bif(list_to_atom(Func),Arity) of
+ true ->
+ analyze(T);
+ false ->
+ [{[],Func,Arity} |
+ analyze(T)]
+ end;
+analyze([{"erlang",Func,Arity}|T]) ->
+ case erl_internal:bif(list_to_atom(Func),Arity) of
+ true ->
+ [{"erlang",Func,Arity}|analyze(T)];
+ false ->
+ analyze(T)
+ end;
+analyze([_|T]) ->
+ analyze(T);
+analyze([]) ->
+ [].
+
+
+count_args([],_,N,false) ->
+ N;
+count_args([],_,N,true) ->
+ N+1;
+count_args(_,0,N,true) ->
+ N+1;
+count_args(_,0,N,false) ->
+ N;
+count_args([Par|T],Level,N,Got) when (Par =:= 40) or
+ (Par =:= 123) or (Par =:= 91) ->
+ count_args(T,Level+1,N,(Level =:= 1) or Got);
+count_args([41|T],1,N,true) ->
+ count_args(T,0,N+1,false);
+count_args([Par|T],Level,N, Got) when (Par =:= 41) or
+ (Par =:= 125) or (Par =:= 93) ->
+ count_args(T,Level-1,N,Got);
+count_args([$,|T],1,N,true) ->
+ count_args(T,1,N+1,false);
+count_args([$ |T],A,B,C) ->
+ count_args(T,A,B,C);
+count_args([_|T],1,N,_) ->
+ count_args(T,1,N,true);
+count_args([_|T],A,B,C) ->
+ count_args(T,A,B,C).
+
+fstrip([],X) ->
+ X;
+fstrip(_,[]) ->
+ [];
+fstrip([H|T1],[H|T2]) ->
+ fstrip(T1,T2);
+fstrip(_,L) ->
+ L.
+
+get_module(X) ->
+ get_module(X,[]).
+get_module([],_) ->
+ [];
+get_module([$:|_],Acc) ->
+ lists:reverse(Acc);
+get_module([40|_],_) -> %(
+ [];
+get_module([H|T],Acc) ->
+ get_module(T,[H|Acc]).
+
+get_function(X) ->
+ get_function(X,[]).
+get_function([],_) ->
+ [];
+get_function([40|_],Acc) -> %(
+ lists:reverse(Acc);
+get_function([H|T],Acc) ->
+ get_function(T,[H|Acc]).
diff --git a/erts/test/autoimport_SUITE_data/dummy.txt b/erts/test/autoimport_SUITE_data/dummy.txt
new file mode 100644
index 0000000000..972643e527
--- /dev/null
+++ b/erts/test/autoimport_SUITE_data/dummy.txt
@@ -0,0 +1,19 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%% Purpouse: Dummy
diff --git a/erts/test/erlc_SUITE.erl b/erts/test/erlc_SUITE.erl
index 437f020f99..4797f78be2 100644
--- a/erts/test/erlc_SUITE.erl
+++ b/erts/test/erlc_SUITE.erl
@@ -21,13 +21,13 @@
%% Tests the erlc command by compiling various types of files.
-export([all/1, compile_erl/1, compile_yecc/1, compile_script/1,
- compile_mib/1, good_citizen/1, deep_cwd/1]).
+ compile_mib/1, good_citizen/1, deep_cwd/1, arg_overflow/1]).
-include_lib("test_server/include/test_server.hrl").
all(suite) ->
[compile_erl, compile_yecc, compile_script, compile_mib,
- good_citizen, deep_cwd].
+ good_citizen, deep_cwd, arg_overflow].
%% Copy from erlc_SUITE_data/include/erl_test.hrl.
@@ -189,6 +189,18 @@ deep_cwd_1(PrivDir) ->
?line true = filelib:is_file("test.beam"),
ok.
+%% Test that a large number of command line switches does not
+%% overflow the argument buffer
+arg_overflow(Config) when is_list(Config) ->
+ ?line {SrcDir, _OutDir, Cmd} = get_cmd(Config),
+ ?line FileName = filename:join(SrcDir, "erl_test_ok.erl"),
+ ?line Args = lists:flatten([ ["-D", integer_to_list(N), "=1 "] ||
+ N <- lists:seq(1,10000) ]),
+ ?line run(Config, Cmd, FileName, Args,
+ ["Warning: function foo/0 is unused\$",
+ "_OK_"]),
+ ok.
+
erlc() ->
case os:find_executable("erlc") of
false ->
diff --git a/erts/test/erlexec_SUITE.erl b/erts/test/erlexec_SUITE.erl
index 164ce9faaf..6adb865f6d 100644
--- a/erts/test/erlexec_SUITE.erl
+++ b/erts/test/erlexec_SUITE.erl
@@ -33,7 +33,7 @@
-export([all/1, init_per_testcase/2, fin_per_testcase/2]).
--export([args_file/1, evil_args_file/1, env/1, args_file_env/1, otp_7461/1, otp_7461_remote/1, otp_8209/1]).
+-export([args_file/1, evil_args_file/1, env/1, args_file_env/1, otp_7461/1, otp_7461_remote/1, otp_8209/1, zdbbl_dist_buf_busy_limit/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -53,7 +53,8 @@ fin_per_testcase(_Case, Config) ->
all(doc) -> [];
all(suite) ->
- [args_file, evil_args_file, env, args_file_env, otp_7461, otp_8209].
+ [args_file, evil_args_file, env, args_file_env, otp_7461, otp_8209,
+ zdbbl_dist_buf_busy_limit].
otp_8209(doc) ->
@@ -330,6 +331,25 @@ otp_7461_remote([halt, Pid]) ->
io:format("halt order from ~p to node ~p\n",[Pid,node()]),
halt().
+zdbbl_dist_buf_busy_limit(doc) ->
+ ["Check +zdbbl flag"];
+zdbbl_dist_buf_busy_limit(suite) ->
+ [];
+zdbbl_dist_buf_busy_limit(Config) when is_list(Config) ->
+ LimKB = 1122233,
+ LimB = LimKB*1024,
+ ?line {ok,[[PName]]} = init:get_argument(progname),
+ ?line SNameS = "erlexec_test_02",
+ ?line SName = list_to_atom(SNameS++"@"++
+ hd(tl(string:tokens(atom_to_list(node()),"@")))),
+ ?line Cmd = PName ++ " -sname "++SNameS++" -setcookie "++
+ atom_to_list(erlang:get_cookie()) ++
+ " +zdbbl " ++ integer_to_list(LimKB),
+ ?line open_port({spawn,Cmd},[]),
+ ?line pong = loop_ping(SName,40),
+ ?line LimB = rpc:call(SName,erlang,system_info,[dist_buf_busy_limit]),
+ ?line ok = cleanup_node(SNameS, 10),
+ ok.
%%
diff --git a/erts/vsn.mk b/erts/vsn.mk
index ce6330e6dd..a5dd62feb2 100644
--- a/erts/vsn.mk
+++ b/erts/vsn.mk
@@ -17,8 +17,8 @@
# %CopyrightEnd%
#
-VSN = 5.8.1
-SYSTEM_VSN = R14B
+VSN = 5.8.2
+SYSTEM_VSN = R14B01
# Port number 4365 in 4.2
# Port number 4366 in 4.3
diff --git a/lib/.gitignore b/lib/.gitignore
index a33916b3bf..340baf5269 100644
--- a/lib/.gitignore
+++ b/lib/.gitignore
@@ -128,6 +128,7 @@
/megaco/src/text/megaco_text_parser_v1.erl
/megaco/src/text/megaco_text_parser_v2.erl
/megaco/src/text/megaco_text_parser_v3.erl
+/megaco/doc/html/mstone1.jpg
# mnesia
diff --git a/lib/appmon/doc/src/notes.xml b/lib/appmon/doc/src/notes.xml
index 29e66411a6..ace163bcad 100644
--- a/lib/appmon/doc/src/notes.xml
+++ b/lib/appmon/doc/src/notes.xml
@@ -30,6 +30,22 @@
</header>
<p>This document describes the changes made to the Appmon application.</p>
+<section><title>Appmon 2.1.13</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ An obsolete compiler directive for native code generation
+ was removed from a source file.</p>
+ <p>
+ Own Id: OTP-8839</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Appmon 2.1.12</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/appmon/src/appmon_web.erl b/lib/appmon/src/appmon_web.erl
index e8a8422a80..fb7144246c 100644
--- a/lib/appmon/src/appmon_web.erl
+++ b/lib/appmon/src/appmon_web.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -38,12 +38,6 @@
%% webtool
-export([configData/0]).
-
-%% The following directive caters for (significantly) faster native
-%% code compilation of one function in this file by the HiPE compiler
-%% on register-poor architectures like the x86.
--compile([{hipe,[{regalloc,graph_color}]}]).
-
-behaviour(gen_server).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/appmon/vsn.mk b/lib/appmon/vsn.mk
index cfcb5d3eb6..fa17345daf 100644
--- a/lib/appmon/vsn.mk
+++ b/lib/appmon/vsn.mk
@@ -1,19 +1 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2010. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-
-APPMON_VSN = 2.1.12
+APPMON_VSN = 2.1.13
diff --git a/lib/asn1/c_src/asn1_erl_driver.c b/lib/asn1/c_src/asn1_erl_driver.c
index fd284e5800..9dd3a0fd7d 100644
--- a/lib/asn1/c_src/asn1_erl_driver.c
+++ b/lib/asn1/c_src/asn1_erl_driver.c
@@ -1407,7 +1407,6 @@ int decode_partial(ErlDrvBinary **drv_binary,unsigned char *in_buf, int in_buf_l
int msg_index_val;
int *msg_index, *tag_index, tmp_index;
int tag_seq_length;
- char tag_code; /* one of ASN1_SKIPPED, ASN1_OPTIONAL, ASN1_CHOOSEN */
int wanted_tag, next_tag;
int buf_end_index = in_buf_len;
int ret = 0, length, old_index;
@@ -1600,7 +1599,7 @@ int get_value(char *out_buf,
{
int len, lenoflen, indef=0, skip_len;
int ret=0;
- int start_index, out_index = 0;
+ int start_index;
/* printf("get_value 1\n\r"); */
if (in_buf[*msg_index] < 0x80){ /* short definite length */
diff --git a/lib/asn1/doc/src/asn1_ug.xml b/lib/asn1/doc/src/asn1_ug.xml
index f2cd073ec8..12d986308f 100644
--- a/lib/asn1/doc/src/asn1_ug.xml
+++ b/lib/asn1/doc/src/asn1_ug.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1997</year><year>2009</year>
+ <year>1997</year><year>2010</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -22,7 +22,7 @@
</legalnotice>
<title>Asn1</title>
- <prepared>ETX/DN/SP Kenneth. Lundin</prepared>
+ <prepared>Kenneth Lundin</prepared>
<docno></docno>
<date>1999-03-25</date>
<rev>D</rev>
@@ -41,17 +41,28 @@
decode functions to be used by Erlang programs sending and
receiving ASN.1 specified data.</item>
<item>Run-time functions used by the generated code.</item>
- <item>Encoding rules supported are <em>BER</em>, the
- specialized BER version <em>DER</em> and the basic form of
- aligned and unaligned variants of <em>PER</em>.</item>
+ <item>The supported encoding rules are:
+ <list>
+ <item>
+ Basic Encoding Rules (<em>BER</em>)
+ </item>
+ <item>
+ Distinguished Encoding Rules (<em>DER</em>), a specialized form of BER that is used in security-conscious applications.
+ </item>
+ <item>
+ Packed Encoding Rules (<em>PER</em>) both the aligned and unaligned variant.
+ </item>
+ </list>
+ </item>
</list>
</section>
<section>
<title>Overview</title>
- <p>ASN.1 (Abstract Syntax Notation 1) defines the abstract
- syntax of information. The purpose of ASN.1 is to have
- a platform independent language to express types using a
+ <p>ASN.1 (Abstract Syntax Notation 1) is a formal language for describing data structures to be exchanged between distributed computer systems.
+ The purpose of ASN.1 is to have
+ a platform and programming language independent notation to express
+ types using a
standardized set of rules for the transformation of values of
a defined type, into a stream of bytes. This stream of bytes
can then be sent on a communication channel set up by the
@@ -102,20 +113,16 @@
[<cite id="DUBUISSON"></cite>], free to download at
<url href="http://www.oss.com/asn1/dubuisson.html">http://www.oss.com/asn1/dubuisson.html </url>.
</p>
- <p>Knowledge of Erlang programming is also essential and reading the book
- <em>Concurrent Programming in ERLANG</em>,
- [<cite id="erlbook2"></cite>], is recommended. Part 1 of this is available on the web in
- <url href="http://www.erlang.org/download/erlang-book-part1.pdf">PDF</url> format.
- </p>
</section>
<section>
<title>Capability</title>
<p>This application covers all features of ASN.1 up to the 1997
- edition of the specification. In the 2002 edition some new
- extensions came up of which there are support only for some of
- them. ECN (Cncoding Control Notation) and XML notation are still
- unsupported. Though, the other features of 2002 edition are
+ edition of the specification. In the 2002 edition of ASN.1 a number of
+ new features where introduced of which some are supported while
+ others are not. For example the
+ ECN (Encoding Control Notation) and XML notation are still
+ unsupported. Though, the other features of the 2002 edition are
fully or partly supported as shown below:</p>
<list type="bulleted">
<item>
@@ -308,7 +315,7 @@ erlc -o ../asnfiles -I ../asnfiles -I /usr/local/standards/asn1 Person.asn
<p>Choice of encoding rules, if omitted <c>ber</c> is the
default. The <c>ber_bin</c> and <c>per_bin</c> options
allows for optimizations and are therefore recommended
- instaed of the <c>ber</c> and <c>per</c> options.</p>
+ instead of the <c>ber</c> and <c>per</c> options.</p>
</item>
<tag><c>-o OutDirectory</c></tag>
<item>
@@ -629,7 +636,7 @@ asn1ct:decode('H323-MESSAGES','SomeChoiceType',Bytes). </pre>
<c>driver</c> options does not affect the encode or decode
result, just the time spent in run-time. When <c>ber_bin</c> and
<c>driver</c> or <c>per_bin, optimize</c> and <c>driver</c> is
- combined the C-code driver is used in choosen parts of encode /
+ combined the C-code driver is used in chosen parts of encode /
decode procedure.
</p>
<table>
@@ -749,11 +756,11 @@ asn1rt:decode('H323-MESSAGES','SomeChoiceType',Bytes). </pre>
you may want to continue running the old asn1 run-time
functionality.</item>
<item>Performance issues: If you have an asn1 system with a lot
- of cross references you may gain in performance. Meassurements
+ of cross references you may gain in performance. Measurements
must be done for each case.</item>
</list>
<p>You may choose either the plain multi file compilation that just
- merges the choosen asn1 specs or the <c>{inline,OutputModule}</c>
+ merges the chosen asn1 specs or the <c>{inline,OutputModule}</c>
that also includes the used asn1 run-time functionality.</p>
<p>For both cases you need to specify which asn1 specs you will
compile in a module that must have the extension
@@ -919,7 +926,7 @@ T5 ::= INTEGER (MIN&lt;..-99)
T6 ::= INTEGER {red(0),blue(1),white(2)}
</pre>
<p>The Erlang representation of an ASN.1 INTEGER is an integer or
- an atom if a so called \011<c>Named NumberList</c> (see T6 above)
+ an atom if a so called <c>Named Number List</c> (see T6 above)
is specified.</p>
<p>Below is an example of Erlang code which assigns values for the
above types: </p>
@@ -934,7 +941,7 @@ T6value3 = white
ASN.1 defined types. This style of value can be passed directly
to the encoder for transformation into a series of bytes.</p>
<p>The decoder will return an atom if the value corresponds to a
- symbol in the Named NumberList.</p>
+ symbol in the Named Number List.</p>
</section>
<section>
@@ -978,8 +985,9 @@ N1 = 'NULL',
<p>The enumerated type can be used, when the value we wish to
describe, may only take one of a set of predefined values.</p>
<pre>
-DaysOfTheWeek ::= ENUMERATED { sunday(1),monday(2),tuesday(3),
-\011wednesday(4),thursday(5),friday(6),saturday(7) }
+DaysOfTheWeek ::= ENUMERATED {
+ sunday(1),monday(2),tuesday(3),
+ wednesday(4),thursday(5),friday(6),saturday(7) }
</pre>
<p>For example to assign a weekday value in Erlang use the same atom
as in the <c>Enumerations</c> of the type definition:</p>
@@ -1273,11 +1281,14 @@ Pdu ::= SEQUENCE {
<p>Values can be assigned in Erlang as shown below:</p>
<pre>
MyPdu = #'Pdu'{a=22,b=77.99,c={0,1,2,3,4},d='NULL'}. </pre>
- <p>It is also possible to specify the value for each component in
- a SEQUENCE or a SET as <c>{ComponentName,Value}</c>. It is not
- recommended and is not supported if the flags <c>per_bin</c> or
- <c>ber_bin</c> and <c>optimize</c> were used when the module was
- compiled.</p>
+<note>
+ <p>
+ In very early versions of the asn1 compiler it was also possible to
+ specify the values of the components in
+ a SEQUENCE or a SET as a list of tuples <c>{ComponentName,Value}</c>.
+ This is no longer supported.
+ </p>
+</note>
<p>The decode functions will return a record as result when decoding
a <c>SEQUENCE</c> or a <c>SET</c>.
<marker id="DEFAULT"></marker>
@@ -1293,13 +1304,13 @@ MyPdu = #'Pdu'{a=22,b=77.99,c={0,1,2,3,4},d='NULL'}. </pre>
<p>For instance, if the following types exists in a file "File.asn":</p>
<pre>
Seq1 ::= SEQUENCE {
-\011a INTEGER DEFAULT 1,
-\011b Seq2 DEFAULT {aa TRUE, bb 15}
+ a INTEGER DEFAULT 1,
+ b Seq2 DEFAULT {aa TRUE, bb 15}
}
Seq2 ::= SEQUENCE {
-\011aa BOOLEAN,
-\011bb INTEGER
+ aa BOOLEAN,
+ bb INTEGER
}
</pre>
<p>Some values and the corresponding encoding in an Erlang terminal
@@ -1331,7 +1342,7 @@ ok
<marker id="DEFAULT DER"></marker>
</p>
<p>But, the DER encoding format has stronger requirements regarding
- default\011values both for SET and SEQUENCE. A more elaborate and time
+ default values both for SET and SEQUENCE. A more elaborate and time
expensive check of default values will take place. The following is
an example with the same types and values as above but with der
encoding format.</p>
@@ -1409,7 +1420,7 @@ Bad ::= SET {i INTEGER,
values is the same for SET as for SEQUENCE, and is supported by
the compiler, <seealso marker="#DEFAULT DER">see above</seealso>.</p>
<p>Moreover, in DER the elements of a SET will be sorted. If a
- component is an untagged choice the sorting have to take place
+ component is an un-tagged choice the sorting have to take place
in run-time. This fact emphasizes the following recommendation
if DER encoding format is used.</p>
<p>The concept of SET is an unusual
@@ -1425,7 +1436,7 @@ Bad ::= SET {i INTEGER,
</section>
<section>
- <title>Notes about Extendability for SEQUENCE and SET</title>
+ <title>Notes about Extend-ability for SEQUENCE and SET</title>
<p>When a SEQUENCE or SET contains an extension marker and
extension components like this:</p>
<pre>
@@ -1498,9 +1509,9 @@ C2 ::= CHOICE {
<section>
<title>Extendable CHOICE</title>
<p>When a CHOICE contains an extension marker and the decoder detects
- an unknown alternative of the CHIOCE the value is represented as:</p>
+ an unknown alternative of the CHOICE the value is represented as:</p>
<pre>
-\011 {asn1_ExtAlt, BytesForOpenType}
+{asn1_ExtAlt, BytesForOpenType}
</pre>
<p>Where <c>BytesForOpenType</c> is a list of bytes constituting the
encoding of the "unknown" CHOICE alternative. </p>
@@ -1630,15 +1641,15 @@ V = #'Emb'{a=["qqqq",[1,2,255]],
the record name is extended with an underscore and the component
name. If the embedded structure is deeper with SEQUENCE, SET or
CHOICE types in the line, each component-/alternative-name will
- be added to the recordname.</p>
+ be added to the record-name.</p>
<p>For example:</p>
<pre>
Seq ::= SEQUENCE{
- a\011CHOICE{
-\011b SEQUENCE {
-\011 c INTEGER
-\011 }
-\011}
+ a CHOICE{
+ b SEQUENCE {
+ c INTEGER
+ }
+ }
} </pre>
<p>will result in the following record:</p>
<pre>
@@ -1650,10 +1661,10 @@ Seq ::= SEQUENCE{
<pre>
Seq ::= SEQUENCE {
a SEQUENCE OF SEQUENCE {
-\011 b
+ b
}
c SET OF SEQUENCE {
-\011 d
+ d
}
} </pre>
<p>This results in the records:</p>
@@ -1802,16 +1813,16 @@ GENERAL-PROCEDURES GENERAL-PROCEDURE ::= {
<pre>
StartMessage ::= SEQUENCE {
msgId GENERAL-PROCEDURE.&amp;id ({GENERAL-PROCEDURES}),
- content GENERAL-PROCEDURE.&amp;Message\011({GENERAL-PROCEDURES}{@msgId}),
+ content GENERAL-PROCEDURE.&amp;Message ({GENERAL-PROCEDURES}{@msgId}),
} </pre>
<p>In the type <c>StartMessage</c> the constraint following the
<c>content</c> field tells that in a value of type
<c>StartMessage</c> the value in the <c>content</c> field must
- come from the same object that is choosen by the <c>msgId</c>
+ come from the same object that is chosen by the <c>msgId</c>
field.</p>
<p>So, the value <c>#'StartMessage'{msgId="home",content="Any Printable String"}</c> is legal to encode as a StartMessage
value, while the value <c>#'StartMessage'{msgId="remote", content="Some String"}</c> is illegal since the constraint
- in StartMessage tells that when you have choosen a value from a
+ in StartMessage tells that when you have chosen a value from a
specific object in the object set GENERAL-PROCEDURES in the
msgId field you have to choose a value from that same object in
the content field too. In this second case it should have been
@@ -1831,7 +1842,7 @@ StartMessage ::= SEQUENCE {
information object sets.
A part of a definition can be supplied as a parameter. For
instance, if a Type is used in a definition with certain
- purpose, one want the typename to express the intention. This
+ purpose, one want the type-name to express the intention. This
can be done with parameterization.</p>
<p>When many types (or an other ASN.1 entity) only differs in some
minor cases, but the structure of the types are similar, only
diff --git a/lib/asn1/doc/src/notes.xml b/lib/asn1/doc/src/notes.xml
index c5ec682e0f..375e859d20 100644
--- a/lib/asn1/doc/src/notes.xml
+++ b/lib/asn1/doc/src/notes.xml
@@ -31,6 +31,50 @@
<p>This document describes the changes made to the asn1 application.</p>
+<section><title>Asn1 1.6.14.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Extension Addition Groups are now supported by the parser
+ and in all backends.</p>
+ <p>
+ Own Id: OTP-8598 Aux Id: seq-11557 </p>
+ </item>
+ <item>
+ <p>
+ Extension Addition Groups are now supported in nested
+ types within a SEQUENCE and CHOICE as well (missed that
+ in previous fix)</p>
+ <p>
+ Own Id: OTP-8797 Aux Id: seq-11557 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Bug in UNALIGNED PER regarding encoding and decoding of
+ constrained numbers with a valuerange > 1024. (Thanks to
+ Vincent de Phily)</p>
+ <p>
+ Own Id: OTP-8779</p>
+ </item>
+ <item>
+ <p>
+ Minor corrections in the User Guide.</p>
+ <p>
+ Own Id: OTP-8829</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Asn1 1.6.14</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/asn1/src/asn1.appup.src b/lib/asn1/src/asn1.appup.src
index 753d308684..2d11eddfbf 100644
--- a/lib/asn1/src/asn1.appup.src
+++ b/lib/asn1/src/asn1.appup.src
@@ -1,111 +1,9 @@
{"%VSN%",
- [
- {"1.6.8",
- [
- {load_module, asn1rt, soft_purge, soft_purge, []},
- {load_module, asn1rt_per_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt_per_bin_rt2ct, soft_purge, soft_purge, []},
- {load_module, asn1rt_uper_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt_ber_bin_v2, soft_purge, soft_purge, []},
- {load_module, asn1rt_check, soft_purge, soft_purge, []},
- {load_module, asn1rt_driver_handler, soft_purge, soft_purge, []},
- {apply, {asn1rt_driver_handler,unload_driver,[]}}
- ]
- },
- {"1.6.8.1",
- [
- {load_module, asn1rt, soft_purge, soft_purge, []},
- {load_module, asn1rt_per_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt_per_bin_rt2ct, soft_purge, soft_purge, []},
- {load_module, asn1rt_uper_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt_ber_bin_v2, soft_purge, soft_purge, []},
- {load_module, asn1rt_check, soft_purge, soft_purge, []},
- {load_module, asn1rt_driver_handler, soft_purge, soft_purge, []},
- {apply, {asn1rt_driver_handler,unload_driver,[]}}
- ]
- },
- {"1.6.9",
- [
- {load_module, asn1rt, soft_purge, soft_purge, []},
- {load_module, asn1rt_per_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt_per_bin_rt2ct, soft_purge, soft_purge, []},
- {load_module, asn1rt_uper_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt_ber_bin_v2, soft_purge, soft_purge, []},
- {load_module, asn1rt_check, soft_purge, soft_purge, []},
- {load_module, asn1rt_driver_handler, soft_purge, soft_purge, []},
- {apply, {asn1rt_driver_handler,unload_driver,[]}}
- ]
- },
- {"1.6.10",
- [
- {load_module, asn1rt, soft_purge, soft_purge, []},
- {load_module, asn1rt_per_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt_per_bin_rt2ct, soft_purge, soft_purge, []},
- {load_module, asn1rt_uper_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt_ber_bin_v2, soft_purge, soft_purge, []},
- {load_module, asn1rt_check, soft_purge, soft_purge, []},
- {load_module, asn1rt_driver_handler, soft_purge, soft_purge, []},
- {apply, {asn1rt_driver_handler,unload_driver,[]}}
- ]
- }
+% This version does not change anything of the runtime modules
+% Only changes in compile time modules and thus no need for upgrade on target
+[
],
[
- {"1.6.8",
- [
- {load_module, asn1rt, soft_purge, soft_purge, []},
- {load_module, asn1rt_per_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt_per_bin_rt2ct, soft_purge, soft_purge, []},
- {load_module, asn1rt_uper_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt_ber_bin_v2, soft_purge, soft_purge, []},
- {load_module, asn1rt_check, soft_purge, soft_purge, []},
- {load_module, asn1rt_driver_handler, soft_purge, soft_purge, []},
- {apply, {asn1rt_driver_handler,unload_driver,[]}}
- ]
- },
- {"1.6.8.1",
- [
- {load_module, asn1rt, soft_purge, soft_purge, []},
- {load_module, asn1rt_per_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt_per_bin_rt2ct, soft_purge, soft_purge, []},
- {load_module, asn1rt_uper_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt_ber_bin_v2, soft_purge, soft_purge, []},
- {load_module, asn1rt_check, soft_purge, soft_purge, []},
- {load_module, asn1rt_driver_handler, soft_purge, soft_purge, []},
- {apply, {asn1rt_driver_handler,unload_driver,[]}}
- ]
- },
- {"1.6.9",
- [
- {load_module, asn1rt, soft_purge, soft_purge, []},
- {load_module, asn1rt_per_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt_per_bin_rt2ct, soft_purge, soft_purge, []},
- {load_module, asn1rt_uper_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt_ber_bin_v2, soft_purge, soft_purge, []},
- {load_module, asn1rt_check, soft_purge, soft_purge, []},
- {load_module, asn1rt_driver_handler, soft_purge, soft_purge, []},
- {apply, {asn1rt_driver_handler,unload_driver,[]}}
- ]
- },
- {"1.6.10",
- [
- {load_module, asn1rt, soft_purge, soft_purge, []},
- {load_module, asn1rt_per_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt_per_bin_rt2ct, soft_purge, soft_purge, []},
- {load_module, asn1rt_uper_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt_ber_bin_v2, soft_purge, soft_purge, []},
- {load_module, asn1rt_check, soft_purge, soft_purge, []},
- {load_module, asn1rt_driver_handler, soft_purge, soft_purge, []},
- {apply, {asn1rt_driver_handler,unload_driver,[]}}
- ]
- }
]}.
diff --git a/lib/asn1/src/asn1_records.hrl b/lib/asn1/src/asn1_records.hrl
index 8a428b744c..59a9acb7e7 100644
--- a/lib/asn1/src/asn1_records.hrl
+++ b/lib/asn1/src/asn1_records.hrl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
%%
@@ -36,7 +36,8 @@
-record(module,{pos,name,defid,tagdefault='EXPLICIT',exports={exports,[]},imports={imports,[]}, extensiondefault=empty,typeorval}).
--record('SEQUENCE',{pname=false,tablecinf=false,components=[]}).
+-record('ExtensionAdditionGroup',{number}).
+-record('SEQUENCE',{pname=false,tablecinf=false,extaddgroup,components=[]}).
-record('SET',{pname=false,sorted=false,tablecinf=false,components=[]}).
-record('ComponentType',{pos,name,typespec,prop,tags,textual_order}).
-record('ObjectClassFieldType',{classname,class,fieldname,type}).
diff --git a/lib/asn1/src/asn1ct.erl b/lib/asn1/src/asn1ct.erl
index ae681a4a78..968468cb7f 100644
--- a/lib/asn1/src/asn1ct.erl
+++ b/lib/asn1/src/asn1ct.erl
@@ -1674,7 +1674,7 @@ create_pdec_inc_command(ModName,
% [concat_sequential(lists:reverse(Comms),
% [LastComm,CompAcc])|Acc]
case lists:reverse(TagCommand) of
- [Atom|Comms]�when is_atom(Atom) ->
+ [Atom|Comms] when is_atom(Atom) ->
[concat_sequential(lists:reverse(Comms),
[Atom,CompAcc])|Acc];
[[Command2,Tag2]|Comms] ->
diff --git a/lib/asn1/src/asn1ct_check.erl b/lib/asn1/src/asn1ct_check.erl
index 54a5c7e727..c6f3b60786 100644
--- a/lib/asn1/src/asn1ct_check.erl
+++ b/lib/asn1/src/asn1ct_check.erl
@@ -22,6 +22,8 @@
%% Main Module for ASN.1 compile time functions
%-compile(export_all).
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([check/2,storeindb/2]).
%-define(debug,1).
-include("asn1_records.hrl").
@@ -3227,7 +3229,7 @@ check_ptype(_S,_PTDef,Ts) when is_record(Ts,objectclass) ->
% check_type(S,Type,ObjSpec={{objectclassname,_},_}) ->
-% check_class(S,ObjSpec);
+ % check_class(S,ObjSpec);
check_type(_S,Type,Ts) when is_record(Type,typedef),
(Type#typedef.checked==true) ->
Ts;
@@ -3357,6 +3359,7 @@ check_type(S=#state{recordtopname=TopName},Type,Ts) when is_record(Ts,type) ->
merge_tags(Tag,?TAG_PRIMITIVE(?N_INTEGER))};
'REAL' ->
check_real(S,Constr),
+
TempNewDef#newt{tag=merge_tags(Tag,?TAG_PRIMITIVE(?N_REAL))};
{'BIT STRING',NamedNumberList} ->
NewL = check_bitstring(S,NamedNumberList,Constr),
@@ -5522,24 +5525,9 @@ check_sequence(S,Type,Comps) ->
Components2 = maybe_automatic_tags(S,Components),
%% check the table constraints from here. The outermost type
%% is Type, the innermost is Comps (the list of components)
- NewComps =
- case check_each_component(S,Type,Components2) of
- NewComponents when is_list(NewComponents) ->
- check_unique_sequence_tags(S,NewComponents),
- NewComponents;
- Ret = {NewComponents,NewEcomps} ->
- TagComps = NewComponents ++
- [Comp#'ComponentType'{prop='OPTIONAL'}|| Comp <- NewEcomps],
- %% extension components are like optionals when it comes to tagging
- check_unique_sequence_tags(S,TagComps),
- Ret;
- Ret = {Root1,NewE,Root2} ->
- TagComps = Root1 ++ [Comp#'ComponentType'{prop='OPTIONAL'}|| Comp <- NewE]++Root2,
- %% This is not correct handling if Extension
- %% contains ExtensionAdditionGroups
- check_unique_sequence_tags(S,TagComps),
- Ret
- end,
+ NewComps = check_each_component2(S,Type,Components2),
+ check_unique_sequence_tags(S,NewComps),
+
%% CRelInf is the "leading attribute" information
%% necessary for code generating of the look up in the
%% object set table,
@@ -5553,12 +5541,45 @@ check_sequence(S,Type,Comps) ->
%% the involved class removed, as the class of the object
%% set.
CompListWithTblInf = get_tableconstraint_info(S,Type,NewComps2),
-
- {CRelInf,CompListWithTblInf};
+ %% If encoding rule is in the PER family the Root Components
+ %% after the second extension mark should be encoded before
+ %% all extensions i.e together with the first Root components
+
+ NewComps3 = textual_order(CompListWithTblInf),
+ CompListTuple =
+ complist_as_tuple(is_erule_per(S#state.erule),NewComps3),
+ {CRelInf,CompListTuple};
Dupl ->
- throw({error,{asn1,{duplicate_components,Dupl}}})
+ throw({error,{asn1,{duplicate_components,Dupl}}})
end.
+complist_as_tuple(Per,CompList) ->
+ complist_as_tuple(Per,CompList,[],[],[],root).
+
+complist_as_tuple(Per,[#'EXTENSIONMARK'{}|T],Acc,Ext,Acc2,root) ->
+ complist_as_tuple(Per,T,Acc,Ext,Acc2,ext);
+complist_as_tuple(Per,[#'EXTENSIONMARK'{}|T],Acc,Ext,Acc2,ext) ->
+ complist_as_tuple(Per,T,Acc,Ext,Acc2,root2);
+complist_as_tuple(_Per,[#'EXTENSIONMARK'{}|_T],_Acc,_Ext,_Acc2,root2) ->
+ throw({error,{asn1,{too_many_extension_marks}}});
+complist_as_tuple(Per,[C|T],Acc,Ext,Acc2,root) ->
+ complist_as_tuple(Per,T,[C|Acc],Ext,Acc2,root);
+complist_as_tuple(Per,[C|T],Acc,Ext,Acc2,ext) ->
+ complist_as_tuple(Per,T,Acc,[C|Ext],Acc2,ext);
+complist_as_tuple(Per,[C|T],Acc,Ext,Acc2,root2) ->
+ complist_as_tuple(Per,T,Acc,Ext,[C|Acc2],root2);
+complist_as_tuple(_Per,[],Acc,_Ext,_Acc2,root) ->
+ lists:reverse(Acc);
+complist_as_tuple(_Per,[],Acc,Ext,_Acc2,ext) ->
+ {lists:reverse(Acc),lists:reverse(Ext)};
+%%complist_as_tuple(_Per = true,[],Acc,Ext,Acc2,root2) ->
+%% {lists:reverse(Acc)++lists:reverse(Acc2),lists:reverse(Ext)};
+complist_as_tuple(_Per,[],Acc,Ext,Acc2,root2) ->
+ {lists:reverse(Acc),lists:reverse(Ext),lists:reverse(Acc2)}.
+
+is_erule_per(Erule) ->
+ lists:member(Erule,[per,per_bin,uper_bin]).
+
expand_components(S, [{'COMPONENTS OF',Type}|T]) ->
CompList = expand_components2(S,get_referenced_type(S,Type#type.def)),
expand_components(S,CompList) ++ expand_components(S,T);
@@ -5601,13 +5622,26 @@ take_only_rootset([#'EXTENSIONMARK'{}|_T])->
take_only_rootset([H|T]) ->
[H|take_only_rootset(T)].
-check_unique_sequence_tags(S,[#'ComponentType'{prop=mandatory}|Rest]) ->
- check_unique_sequence_tags(S,Rest);
-check_unique_sequence_tags(S,[C|Rest]) when is_record(C,'ComponentType') ->
+check_unique_sequence_tags(S,CompList) ->
+ TagComps = case complist_as_tuple(false,CompList) of
+ {R1,Ext,R2} ->
+ R1 ++ [C#'ComponentType'{prop='OPTIONAL'}||
+ C = #'ComponentType'{} <- Ext]++R2;
+ {R1,Ext} ->
+ R1 ++ [C#'ComponentType'{prop='OPTIONAL'}||
+ C = #'ComponentType'{} <- Ext];
+ _ ->
+ CompList
+ end,
+ check_unique_sequence_tags0(S,TagComps).
+
+check_unique_sequence_tags0(S,[#'ComponentType'{prop=mandatory}|Rest]) ->
+ check_unique_sequence_tags0(S,Rest);
+check_unique_sequence_tags0(S,[C=#'ComponentType'{}|Rest]) ->
check_unique_sequence_tags1(S,Rest,[C]);% optional or default
-check_unique_sequence_tags(S,[_ExtensionMarker|Rest]) ->
- check_unique_sequence_tags(S,Rest);
-check_unique_sequence_tags(_S,[]) ->
+check_unique_sequence_tags0(S,[_ExtensionMarker|Rest]) ->
+ check_unique_sequence_tags0(S,Rest);
+check_unique_sequence_tags0(_S,[]) ->
true.
check_unique_sequence_tags1(S,[C|Rest],Acc) when is_record(C,'ComponentType') ->
@@ -5807,8 +5841,10 @@ get_least_tag(TagList) ->
%% adds the textual order to the components to keep right order of
%% components in the asn1-value.
textual_order(Cs) ->
- Fun = fun(C,Index) ->
- {C#'ComponentType'{textual_order=Index},Index+1}
+ Fun = fun(C=#'ComponentType'{},Index) ->
+ {C#'ComponentType'{textual_order=Index},Index+1};
+ (Other,Index) ->
+ {Other,Index}
end,
{NewCs,_} = textual_order(Cs,Fun,1),
NewCs.
@@ -5879,7 +5915,6 @@ check_selectiontype2(S,Name,TypeDef) ->
error({type,Msg,S})
end.
-
check_restrictedstring(_S,_Def,_Constr) ->
ok.
@@ -5899,16 +5934,16 @@ check_choice(S,Type,Components) when is_list(Components) ->
[] ->
%% sort_canonical(Components),
Components2 = maybe_automatic_tags(S,Components),
- %NewComps =
- case check_each_alternative(S,Type,Components2) of
- {NewComponents,NewEcomps} ->
- check_unique_tags(S,NewComponents ++ NewEcomps),
- {NewComponents,NewEcomps};
- NewComponents ->
- check_unique_tags(S,NewComponents),
- NewComponents
- end;
-
+ NewComps = check_each_alternative2(S,Type,Components2),
+ %% ExtensionAdditionGroup markers i.e '[[' ']]' are not
+ %% significant for encoding/decoding a choice
+ %% therefore we remove them here
+ NewComps2 = lists:filter(fun(#'ExtensionAdditionGroup'{}) -> false;
+ ('ExtensionAdditionGroupEnd') -> false;
+ (_) -> true
+ end,NewComps),
+ check_unique_tags(S,NewComps2),
+ complist_as_tuple(is_erule_per(S#state.erule),NewComps2);
Dupl ->
throw({error,{asn1,{duplicate_choice_alternatives,Dupl}}})
end;
@@ -6036,12 +6071,17 @@ check_unique2([_|T],Pos,Acc) ->
check_unique2([],_,Acc) ->
lists:reverse(Acc).
-check_each_component(S,Type,Components) ->
- check_each_component(S,Type,Components,[],[],[],root1).
-check_each_component(S = #state{abscomppath=Path,recordtopname=TopName},Type,
- [C|Ct],Acc,Extacc,Acc2,Ext) when is_record(C,'ComponentType') ->
- #'ComponentType'{name=Cname,typespec=Ts,prop=Prop} = C,
+%% Replaces check_each_component and does the same work except that
+%% it keeps the complist as a flat list and does not create a tuple with root and
+%% extensions separated
+check_each_component2(S,Type,Components) ->
+ check_each_component2(S,Type,Components,[]).
+
+check_each_component2(S = #state{abscomppath=Path,recordtopname=TopName},
+ Type,
+ [C = #'ComponentType'{name=Cname,typespec=Ts,prop=Prop}|Ct],
+ Acc) ->
NewAbsCPath =
case Ts#type.def of
#'Externaltypereference'{} -> [];
@@ -6058,75 +6098,48 @@ check_each_component(S = #state{abscomppath=Path,recordtopname=TopName},Type,
DefaultValue -> {'DEFAULT',DefaultValue}
end,
NewC = C#'ComponentType'{typespec=CheckedTs,prop=NewProp,tags=NewTags},
- case Ext of
- root1 ->
- check_each_component(S,Type,Ct,[NewC|Acc],Extacc,Acc2,Ext);
- ext ->
- check_each_component(S,Type,Ct,Acc,[NewC|Extacc],Acc2,Ext);
- root2 ->
- check_each_component(S,Type,Ct,Acc,Extacc,[NewC|Acc2],Ext)
- end;
-check_each_component(S,Type,[_|Ct],Acc,Extacc,Acc2,root1) -> % skip 'EXTENSIONMARK'
- check_each_component(S,Type,Ct,Acc,Extacc,Acc2,ext);
-check_each_component(S,Type,[_|Ct],Acc,Extacc,Acc2,ext) -> % skip 'EXTENSIONMARK'
- check_each_component(S,Type,Ct,Acc,Extacc,Acc2,root2);
-check_each_component(_S,_,[_C|_Ct],_,_,_,root2) -> % 'EXTENSIONMARK'
- throw({error,{asn1,{too_many_extension_marks}}});
-check_each_component(_S,_,[],Acc,Extacc,_,ext) ->
- {lists:reverse(Acc),lists:reverse(Extacc)};
-check_each_component(_S,_,[],Acc1,ExtAcc,Acc2,root2) ->
- {lists:reverse(Acc1),lists:reverse(ExtAcc),lists:reverse(Acc2)};
-check_each_component(_S,_,[],Acc,_,_,root1) ->
+ check_each_component2(S,Type,Ct,[NewC|Acc]);
+
+check_each_component2(S,Type,[OtherMarker|Ct],Acc) ->
+ %% let 'EXTENSIONMARK' and 'ExtensionAdditionGroup' markers pass through as is
+ check_each_component2(S,Type,Ct,[OtherMarker|Acc]);
+check_each_component2(_S,_,[],Acc) ->
lists:reverse(Acc).
-%% check_each_alternative(S,Type,{Rlist,ExtList}) ->
+
+%% check_each_alternative2(S,Type,{Rlist,ExtList}) ->
%% {check_each_alternative(S,Type,Rlist),
%% check_each_alternative(S,Type,ExtList)};
-check_each_alternative(S,Type,[C|Ct]) ->
- check_each_alternative(S,Type,[C|Ct],[],[],noext).
+check_each_alternative2(S,Type,[C|Ct]) ->
+ check_each_alternative2(S,Type,[C|Ct],[]).
-check_each_alternative(S=#state{abscomppath=Path,recordtopname=TopName},Type,[C|Ct],
- Acc,Extacc,Ext) when is_record(C,'ComponentType') ->
- #'ComponentType'{name=Cname,typespec=Ts,prop=_Prop} = C,
+check_each_alternative2(S=#state{abscomppath=Path,recordtopname=TopName},
+ Type,
+ [C = #'ComponentType'{name=Cname,typespec=Ts}|Ct],
+ Acc) ->
NewAbsCPath =
case Ts#type.def of
#'Externaltypereference'{} -> [];
_ -> [Cname|Path]
end,
- NewState =
- S#state{abscomppath=NewAbsCPath,recordtopname=[Cname|TopName]},
- CheckedTs = check_type(NewState,Type,Ts),
+ CheckedTs = check_type(S#state{abscomppath=NewAbsCPath,
+ recordtopname=[Cname|TopName]},Type,Ts),
NewTags = get_taglist(S,CheckedTs),
+
NewC = C#'ComponentType'{typespec=CheckedTs,tags=NewTags},
- case Ext of
- noext ->
- check_each_alternative(S,Type,Ct,[NewC|Acc],Extacc,Ext);
- ext ->
- check_each_alternative(S,Type,Ct,Acc,[NewC|Extacc],Ext)
- end;
+ check_each_alternative2(S,Type,Ct,[NewC|Acc]);
-check_each_alternative(S,Type,[_|Ct],Acc,Extacc,noext) -> % skip 'EXTENSIONMARK'
- check_each_alternative(S,Type,Ct,Acc,Extacc,ext);
-check_each_alternative(_S,_,[_C|_Ct],_,_,ext) -> % skip 'EXTENSIONMARK'
- throw({error,{asn1,{too_many_extension_marks}}});
-check_each_alternative(_S,_,[],Acc,Extacc,ext) ->
- {lists:reverse(Acc),lists:reverse(Extacc)};
-check_each_alternative(_S,_,[],Acc,_,noext) ->
+check_each_alternative2(S,Type,[OtherMarker|Ct],Acc) ->
+ %% let 'EXTENSIONMARK' and 'ExtensionAdditionGroup' markers pass through as is
+ check_each_alternative2(S,Type,Ct,[OtherMarker|Acc]);
+check_each_alternative2(_S,_,[],Acc) ->
lists:reverse(Acc).
+
%% componentrelation_leadingattr/2 searches the structure for table
%% constraints, if any is found componentrelation_leadingattr/5 is
%% called.
componentrelation_leadingattr(S,CompList) ->
- Cs =
- case CompList of
- {Comp1, EComps, Comp2} ->
- Comp1++EComps++Comp2;
- {Components,EComponents} when is_list(Components) ->
- Components ++ EComponents;
- CompList when is_list(CompList) ->
- CompList
- end,
%% get_simple_table_if_used/2 should find out whether there are any
%% component relation constraints in the entire tree of Cs1 that
@@ -6135,12 +6148,22 @@ componentrelation_leadingattr(S,CompList) ->
%% componentrelation_leadingattr/6. The step when the leading
%% attribute and the syntax tree is modified to support the code
%% generating.
- case get_simple_table_if_used(S,Cs) of
+ case get_simple_table_if_used(S,CompList) of
[] -> {false,CompList};
- STList ->
- componentrelation_leadingattr(S,Cs,Cs,STList,[],[])
+ _ ->
+ componentrelation_leadingattr(S,CompList,CompList,[],[])
end.
+
+%%FIXME expand_ExtAddGroups([C#'ExtensionAdditionGroup'{components=ExtAdds}|T],
+%% CurrPos,PosAcc,CompAcc) ->
+%% expand_ExtAddGroups(T,CurrPos+ L = lenght(ExtAdds),[{CurrPos,L}|PosAcc],ExtAdds++CompAcc);
+%% expand_ExtAddGroups([C|T],CurrPos,PosAcc,CompAcc) ->
+%% expand_ExtAddGroups(T,CurrPos+ 1,PosAcc,[C|CompAcc]);
+%% expand_ExtAddGroups([],_CurrPos,PosAcc,CompAcc) ->
+%% {lists:reverse(PosAcc),lists:reverse(CompAcc)}.
+
+
%% componentrelation_leadingattr/6 when all components are searched
%% the new modified components are returned together with the "leading
%% attribute" information, which later is stored in the tablecinf
@@ -6150,11 +6173,12 @@ componentrelation_leadingattr(S,CompList) ->
%% is used in code generating phase too, to recognice the proper
%% components for "open type" encoding and to propagate the result of
%% the object set lookup when needed.
-componentrelation_leadingattr(_,[],_CompList,_,[],NewCompList) ->
+componentrelation_leadingattr(_,[],_CompList,[],NewCompList) ->
{false,lists:reverse(NewCompList)};
-componentrelation_leadingattr(_,[],_CompList,_,LeadingAttr,NewCompList) ->
+componentrelation_leadingattr(_,[],_CompList,LeadingAttr,NewCompList) ->
{lists:last(LeadingAttr),lists:reverse(NewCompList)}; %send all info in Ts later
-componentrelation_leadingattr(S,[C|Cs],CompList,STList,Acc,CompAcc) ->
+
+componentrelation_leadingattr(S,[C= #'ComponentType'{}|Cs],CompList,Acc,CompAcc) ->
{LAAcc,NewC} =
case catch componentrelation1(S,C#'ComponentType'.typespec,
[C#'ComponentType'.name]) of
@@ -6205,7 +6229,7 @@ componentrelation_leadingattr(S,[C|Cs],CompList,STList,Acc,CompAcc) ->
%% no constraint was found
{[],C}
end,
- componentrelation_leadingattr(S,Cs,CompList,STList,LAAcc++Acc,
+ componentrelation_leadingattr(S,Cs,CompList,LAAcc++Acc,
[NewC|CompAcc]).
object_set_mod_name(_S,ObjSet) when is_atom(ObjSet) ->
@@ -6228,11 +6252,9 @@ object_set_mod_name(S,#'Externaltypereference'{module=M,type=T}) ->
%% generation of the look up functionality in the object set table are
%% returned.
get_simple_table_if_used(S,Cs) ->
- CNames = lists:map(fun(#'ComponentType'{name=Name}) -> Name;
- (_) -> [] %% in case of extension marks
- end,
- Cs),
- RefedSimpleTable=any_component_relation(S,Cs,CNames,[],[]),
+ CNames = [Name||#'ComponentType'{name=Name}<-Cs],
+ JustComponents = [C || C = #'ComponentType'{}<-Cs],
+ RefedSimpleTable=any_component_relation(S,JustComponents,CNames,[],[]),
get_simple_table_info(S,Cs,remove_doubles(RefedSimpleTable)).
remove_doubles(L) ->
@@ -6336,9 +6358,7 @@ simple_table_info(S,Type,_) ->
%% beginning of the search. CNames holds the names of all components
%% of the start level, this info is used if an outermost at-notation
%% is found to check the validity of the at-list.
-any_component_relation(S,[C|Cs],CNames,NamePath,Acc) ->
- CName = C#'ComponentType'.name,
- Type = C#'ComponentType'.typespec,
+any_component_relation(S,[#'ComponentType'{name=CName,typespec=Type}|Cs],CNames,NamePath,Acc) ->
CRelPath =
case constraint_member(componentrelation,Type#type.constraint) of
%% [{componentrelation,_,AtNotation}] ->
@@ -6358,9 +6378,9 @@ any_component_relation(S,[C|Cs],CNames,NamePath,Acc) ->
case {Type#type.inlined,
asn1ct_gen:type(asn1ct_gen:get_inner(Type#type.def))} of
{no,{constructed,bif}} ->
+
{InnerCs,NewNamePath} =
case get_components(Type#type.def) of
- {IC1,_IC2} -> {IC1 ++ IC1,[CName|NamePath]};
T when is_record(T,type) -> {T,NamePath};
IC -> {IC,[CName|NamePath]}
end,
@@ -6384,16 +6404,18 @@ any_component_relation(S,Type,CNames,NamePath,Acc) when is_record(Type,type) ->
case {Type#type.inlined,
asn1ct_gen:type(asn1ct_gen:get_inner(Type#type.def))} of
{no,{constructed,bif}} ->
- InnerCs =
- case get_components(Type#type.def) of
- {IC1,_IC2} -> IC1 ++ IC1;
- IC -> IC
- end,
+ InnerCs = get_components(Type#type.def),
any_component_relation(S,InnerCs,CNames,NamePath,[]);
_ ->
[]
end,
InnerAcc ++ CRelPath ++ Acc;
+%% Just skip the markers for ExtensionAdditionGroup start and end
+%% in this function
+any_component_relation(S,[#'ExtensionAdditionGroup'{}|Cs],CNames,NamePath,Acc) ->
+ any_component_relation(S,Cs,CNames,NamePath,Acc);
+any_component_relation(S,['ExtensionAdditionGroupEnd'|Cs],CNames,NamePath,Acc) ->
+ any_component_relation(S,Cs,CNames,NamePath,Acc);
any_component_relation(_,[],_,_,Acc) ->
Acc.
@@ -6456,11 +6478,11 @@ get_components(Def) ->
get_components(any,Def).
get_components(_,#'SEQUENCE'{components=Cs}) ->
- Cs;
+ tuple2complist(Cs);
get_components(_,#'SET'{components=Cs}) ->
- Cs;
+ tuple2complist(Cs);
get_components(_,{'CHOICE',Cs}) ->
- Cs;
+ tuple2complist(Cs);
%do not step in inlined structures
get_components(any,{'SEQUENCE OF',T = #type{def=_Def,inlined=no}}) ->
% get_components(any,Def);
@@ -6471,6 +6493,13 @@ get_components(any,{'SET OF',T = #type{def=_Def,inlined=no}}) ->
get_components(_,_) ->
[].
+tuple2complist({R,E}) ->
+ R ++ E;
+tuple2complist({R1,E,R2}) ->
+ R1 ++ E ++ R2;
+tuple2complist(List) when is_list(List) ->
+ List.
+
get_choice_components(_S,{'CHOICE',Components}) when is_list(Components)->
Components;
get_choice_components(_S,{'CHOICE',{C1,C2}}) when is_list(C1),is_list(C2) ->
@@ -6731,8 +6760,7 @@ get_tableconstraint_info(S,Type,CheckedTs) ->
get_tableconstraint_info(_S,_Type,[],Acc) ->
lists:reverse(Acc);
-get_tableconstraint_info(S,Type,[C|Cs],Acc) ->
- CheckedTs = C#'ComponentType'.typespec,
+get_tableconstraint_info(S,Type,[C=#'ComponentType'{typespec=CheckedTs}|Cs],Acc) ->
AccComp =
case CheckedTs#type.def of
%% ObjectClassFieldType
@@ -6768,7 +6796,9 @@ get_tableconstraint_info(S,Type,[C|Cs],Acc) ->
_ ->
C
end,
- get_tableconstraint_info(S,Type,Cs,[AccComp|Acc]).
+ get_tableconstraint_info(S,Type,Cs,[AccComp|Acc]);
+get_tableconstraint_info(S,Type,[C|Cs],Acc) ->
+ get_tableconstraint_info(S,Type,Cs,[C|Acc]).
get_referenced_fieldname([{_,FirstFieldname}]) ->
{FirstFieldname,[]};
@@ -6850,7 +6880,9 @@ get_taglist(S,Type) when is_record(Type,type) ->
[asn1ct_gen:def_to_tag(Tag)]
end;
get_taglist(S,{'CHOICE',{Rc,Ec}}) ->
- get_taglist(S,{'CHOICE',Rc ++ Ec});
+ get_taglist1(S,Rc ++ Ec);
+get_taglist(S,{'CHOICE',{R1,E,R2}}) ->
+ get_taglist1(S,R1 ++ E ++ R2);
get_taglist(S,{'CHOICE',Components}) ->
get_taglist1(S,Components);
%% ObjectClassFieldType OTP-4390
diff --git a/lib/asn1/src/asn1ct_constructed_ber.erl b/lib/asn1/src/asn1ct_constructed_ber.erl
index 51a241ffbd..77b78dcac7 100644
--- a/lib/asn1/src/asn1ct_constructed_ber.erl
+++ b/lib/asn1/src/asn1ct_constructed_ber.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
%%
@@ -71,13 +71,15 @@ gen_encode_sequence(Erules,Typename,D) when is_record(D,type) ->
ok
end,
- {SeqOrSet,TableConsInfo,CompList} =
+ {SeqOrSet,TableConsInfo,CompList0} =
case D#type.def of
#'SEQUENCE'{tablecinf=TCI,components=CL} ->
{'SEQUENCE',TCI,CL};
#'SET'{tablecinf=TCI,components=CL} ->
{'SET',TCI,CL}
end,
+ %% filter away extensionAdditiongroup markers
+ CompList = filter_complist(CompList0),
Ext = extensible(CompList),
CompList1 = case CompList of
{Rl1,El,Rl2} -> Rl1 ++ El ++ Rl2;
@@ -189,7 +191,11 @@ gen_encode_sequence(Erules,Typename,D) when is_record(D,type) ->
gen_decode_sequence(Erules,Typename,D) when is_record(D,type) ->
asn1ct_name:start(),
asn1ct_name:new(tag),
- #'SEQUENCE'{tablecinf=TableConsInfo,components=CList} = D#type.def,
+ #'SEQUENCE'{tablecinf=TableConsInfo,components=CList0} = D#type.def,
+
+ %% filter away extensionAdditiongroup markers
+ CList = filter_complist(CList0),
+
Ext = extensible(CList),
{CompList,CompList2} = case CList of
{Rl1,El,Rl2} -> {Rl1 ++ El ++ Rl2,CList};
@@ -369,7 +375,10 @@ gen_decode_set(Erules,Typename,D) when is_record(D,type) ->
asn1ct_name:clear(),
asn1ct_name:new(term),
asn1ct_name:new(tag),
- #'SET'{components=TCompList} = D#type.def,
+ #'SET'{components=TCompList0} = D#type.def,
+
+ %% filter away extensionAdditiongroup markers
+ TCompList = filter_complist(TCompList0),
Ext = extensible(TCompList),
ToOptional = fun(mandatory) ->
'OPTIONAL';
@@ -1473,6 +1482,22 @@ extensible({RootList,ExtList}) ->
{ext,length(RootList)+1,length(ExtList)};
extensible({_Rl1,_ExtL,_Rl2}) ->
extensible.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% filter away ExtensionAdditionGroup start and end marks since these
+%% have no significance for the BER encoding
+%%
+filter_complist(CompList) when is_list(CompList) ->
+ lists:filter(fun(#'ExtensionAdditionGroup'{}) ->
+ false;
+ ('ExtensionAdditionGroupEnd') ->
+ false;
+ (_) ->
+ true
+ end, CompList);
+filter_complist({Root,Ext}) ->
+ {Root,filter_complist(Ext)};
+filter_complist({Root1,Ext,Root2}) ->
+ {Root1,filter_complist(Ext),Root2}.
print_attribute_comment(InnerType,Pos,Prop) ->
CommentLine = "%%-------------------------------------------------",
diff --git a/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl b/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl
index a55ac9db8e..e3be914af4 100644
--- a/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl
+++ b/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -75,13 +75,15 @@ gen_encode_sequence(Erules,Typename,D) when is_record(D,type) ->
"Val"
end,
- {SeqOrSet,TableConsInfo,CompList} =
+ {SeqOrSet,TableConsInfo,CompList0} =
case D#type.def of
#'SEQUENCE'{tablecinf=TCI,components=CL} ->
{'SEQUENCE',TCI,CL};
#'SET'{tablecinf=TCI,components=CL} ->
{'SET',TCI,CL}
end,
+ %% filter away extensionAdditiongroup markers
+ CompList = filter_complist(CompList0),
Ext = extensible(CompList),
CompList1 = case CompList of
{Rl1,El,Rl2} -> Rl1 ++ El ++ Rl2;
@@ -183,7 +185,10 @@ gen_decode_sequence(Erules,Typename,D) when is_record(D,type) ->
asn1ct_name:start(),
asn1ct_name:clear(),
asn1ct_name:new(tag),
- #'SEQUENCE'{tablecinf=TableConsInfo,components=CList} = D#type.def,
+ #'SEQUENCE'{tablecinf=TableConsInfo,components=CList0} = D#type.def,
+
+ %% filter away extensionAdditiongroup markers
+ CList = filter_complist(CList0),
Ext = extensible(CList),
{CompList,CompList2} =
case CList of
@@ -345,7 +350,9 @@ gen_decode_set(Erules,Typename,D) when is_record(D,type) ->
asn1ct_name:clear(),
%% asn1ct_name:new(term),
asn1ct_name:new(tag),
- #'SET'{tablecinf=TableConsInfo,components=TCompList} = D#type.def,
+ #'SET'{tablecinf=TableConsInfo,components=TCompList0} = D#type.def,
+ %% filter away extensionAdditiongroup markers
+ TCompList = filter_complist(TCompList0),
Ext = extensible(TCompList),
ToOptional = fun(mandatory) ->
'OPTIONAL';
@@ -1426,6 +1433,22 @@ extensible({RootList,ExtList}) ->
{ext,length(RootList)+1,length(ExtList)};
extensible({_Rl1,_Ext,_Rl2}) ->
extensible.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% filter away ExtensionAdditionGroup start and end marks since these
+%% have no significance for the BER encoding
+%%
+filter_complist(CompList) when is_list(CompList) ->
+ lists:filter(fun(#'ExtensionAdditionGroup'{}) ->
+ false;
+ ('ExtensionAdditionGroupEnd') ->
+ false;
+ (_) ->
+ true
+ end, CompList);
+filter_complist({Root,Ext}) ->
+ {Root,filter_complist(Ext)};
+filter_complist({Root1,Ext,Root2}) ->
+ {Root1,filter_complist(Ext),Root2}.
print_attribute_comment(InnerType,Pos,Cname,Prop) ->
diff --git a/lib/asn1/src/asn1ct_constructed_per.erl b/lib/asn1/src/asn1ct_constructed_per.erl
index 2a1c0ebc6b..cce6eb9831 100644
--- a/lib/asn1/src/asn1ct_constructed_per.erl
+++ b/lib/asn1/src/asn1ct_constructed_per.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
%%
@@ -46,18 +46,29 @@ gen_encode_constructed(Erule,Typename,D) when is_record(D,type) ->
asn1ct_name:start(),
asn1ct_name:new(term),
asn1ct_name:new(bytes),
- {CompList,TableConsInfo} =
+ {ExtAddGroup,TmpCompList,TableConsInfo} =
case D#type.def of
- #'SEQUENCE'{tablecinf=TCI,components=CL} ->
- {CL,TCI};
+ #'SEQUENCE'{tablecinf=TCI,components=CL,extaddgroup=ExtAddGroup0} ->
+ {ExtAddGroup0,CL,TCI};
#'SET'{tablecinf=TCI,components=CL} ->
- {CL,TCI}
+ {undefined,CL,TCI}
end,
+
+ CompList = case ExtAddGroup of
+ undefined ->
+ TmpCompList;
+ _ when is_integer(ExtAddGroup) ->
+ %% This is a fake SEQUENCE representing an ExtensionAdditionGroup
+ %% Reset the textual order so we get the right
+ %% index of the components
+ [Comp#'ComponentType'{textual_order=undefined}||
+ Comp<-TmpCompList]
+ end,
case Typename of
['EXTERNAL'] ->
- emit({{var,asn1ct_name:next(val)},
+ emit({{next,val},
" = asn1rt_check:transform_to_EXTERNAL1990(",
- {var,asn1ct_name:curr(val)},"),",nl}),
+ {curr,val},"),",nl}),
asn1ct_name:new(val);
_ ->
ok
@@ -66,23 +77,40 @@ gen_encode_constructed(Erule,Typename,D) when is_record(D,type) ->
{[],EmptyCL} when EmptyCL == {[],[],[]};EmptyCL == {[],[]};EmptyCL == [] ->
emit(["%%Variable setting just to eliminate ",
"compiler warning for unused vars!",nl,
- "_Val = ",{var,asn1ct_name:curr(val)},",",nl]);
+ "_Val = ",{curr,val},",",nl]);
{[],_} ->
- emit([{var,asn1ct_name:next(val)}," = ?RT_PER:list_to_record("]),
+ emit([{next,val}," = ?RT_PER:list_to_record("]),
emit(["'",asn1ct_gen:list2rname(Typename),"'"]),
- emit([", ",{var,asn1ct_name:curr(val)},"),",nl]);
+ emit([", ",{curr,val},"),",nl]);
_ ->
Fixoptcall = ",Opt} = ?RT_PER:fixoptionals(",
- emit({"{",{var,asn1ct_name:next(val)},Fixoptcall,
+ emit({"{",{next,val},Fixoptcall,
{asis,Optionals},",",length(Optionals),
- ",",{var,asn1ct_name:curr(val)},"),",nl})
+ ",",{curr,val},"),",nl})
end,
asn1ct_name:new(val),
- Ext = extensible(CompList),
+ Ext = extensible_enc(CompList),
case Ext of
{ext,_,NumExt} when NumExt > 0 ->
- emit(["Extensions = ?RT_PER:fixextensions(",{asis,Ext},
- ", ",{curr,val},"),",nl]);
+ case extgroup_pos_and_length(CompList) of
+ {extgrouppos,ExtGroupPos,ExtGroupLen} ->
+ Elements = make_elements(ExtGroupPos+1,
+ "Val1",lists:seq(1,ExtGroupLen)),
+ emit([
+ {next,val}," = case [X || X <- [",Elements,
+ "],X =/= asn1_NOVALUE] of",nl,
+ "[] -> ",{curr,val},";",nl,
+ "_ -> setelement(",{asis,ExtGroupPos+1},",",
+ {curr,val},",",
+ "{extaddgroup,", Elements,"})",nl,
+ "end,",nl]),
+ asn1ct_name:new(val);
+ _ -> % no extensionAdditionGroup
+ ok
+ end,
+ asn1ct_name:new(tmpval),
+ emit(["Extensions = ?RT_PER:fixextensions(",{asis,Ext},",",
+ {curr,val},"),",nl]);
_ -> true
end,
EncObj =
@@ -188,9 +216,10 @@ gen_decode_constructed(Erules,Typename,D) when is_record(D,type) ->
#'SEQUENCE'{tablecinf=TCI,components=CL} ->
{add_textual_order(CL),TCI};
#'SET'{tablecinf=TCI,components=CL} ->
- {add_textual_order(CL),TCI}
+%% {add_textual_order(CL),TCI}
+ {CL,TCI} % the textual order is already taken care of
end,
- Ext = extensible(CompList),
+ Ext = extensible_dec(CompList),
MaybeComma1 = case Ext of
{ext,_Pos,_NumExt} ->
gen_dec_extension_value("Bytes"),
@@ -243,8 +272,9 @@ gen_decode_constructed(Erules,Typename,D) when is_record(D,type) ->
{false,false,false}
end
end,
+ NewCompList = wrap_compList(CompList),
{AccTerm,AccBytes} =
- gen_dec_components_call(Erules,Typename,CompList,MaybeComma2,DecObjInf,Ext,length(Optionals)),
+ gen_dec_components_call(Erules,Typename,NewCompList,MaybeComma2,DecObjInf,Ext,length(Optionals)),
case asn1ct_name:all(term) of
[] -> emit(MaybeComma2); % no components at all
_ -> emit({com,nl})
@@ -284,26 +314,24 @@ gen_decode_constructed(Erules,Typename,D) when is_record(D,type) ->
emit(" {ASN11994Format,");
_ ->
emit(["{{'",RecordName,"'"]),
- mkvlist(textual_order(CompList,asn1ct_name:all(term))),
+ %% CompList is used here because we don't want
+ %% ExtensionAdditionGroups to be wrapped in SEQUENCES when
+ %% we are ordering the fields according to textual order
+ mkvlist(textual_order(to_encoding_order(CompList),asn1ct_name:all(term))),
emit("},")
end,
- emit({{var,asn1ct_name:curr(bytes)},"}"}),
+ emit({{curr,bytes},"}"}),
emit({".",nl,nl}).
textual_order([#'ComponentType'{textual_order=undefined}|_],TermList) ->
TermList;
textual_order(CompList,TermList) when is_list(CompList) ->
- TermTuple = list_to_tuple(TermList), %% ['Term1','Term2',...'TermN']
- %% OrderList is ordered by canonical order of tags
- TmpTuple = TermTuple,
- OrderList = [Ix||#'ComponentType'{textual_order=Ix} <- CompList],
- Fun = fun(X,{Tpl,Ix}) ->
-
- {setelement(X,Tpl,element(Ix,TermTuple)),Ix+1}
- end,
- {Ret,_} = lists:foldl(Fun,{TmpTuple,1},OrderList),
-%% io:format("TermTuple: ~p~nOrderList: ~p~nRet: ~p~n",[TermTuple,OrderList,tuple_to_list(Ret)]),
- tuple_to_list(Ret);
+ OrderList = [Ix||#'ComponentType'{textual_order=Ix} <- CompList],
+ [Term||{_,Term}<-
+ lists:sort(lists:zip(OrderList,
+ lists:sublist(TermList,length(OrderList))))];
+ %% sublist is just because Termlist can sometimes be longer than
+ %% OrderList, which it really shouldn't
textual_order({Root,Ext},TermList) ->
textual_order(Root ++ Ext,TermList);
textual_order({Root1,Ext,Root2},TermList) ->
@@ -379,7 +407,7 @@ emit_opt_or_mand_check(Val,Term) ->
gen_encode_choice(Erule,Typename,D) when is_record(D,type) ->
{'CHOICE',CompList} = D#type.def,
emit({"[",nl}),
- Ext = extensible(CompList),
+ Ext = extensible_enc(CompList),
gen_enc_choice(Erule,Typename,CompList,Ext),
emit({nl,"].",nl}).
@@ -388,7 +416,7 @@ gen_decode_choice(Erules,Typename,D) when is_record(D,type) ->
asn1ct_name:clear(),
asn1ct_name:new(bytes),
{'CHOICE',CompList} = D#type.def,
- Ext = extensible(CompList),
+ Ext = extensible_enc(CompList),
gen_dec_choice(Erules,Typename,CompList,Ext),
emit({".",nl}).
@@ -558,12 +586,53 @@ mkvlist2([H|T]) ->
mkvlist2([]) ->
true.
-extensible(CompList) when is_list(CompList) ->
+
+extensible_dec(CompList) when is_list(CompList) ->
noext;
-extensible({RootList,ExtList}) ->
- {ext,length(RootList)+1,length(ExtList)};
-extensible({Rl1,Ext,_Rl2}) ->
- {ext,length(Rl1)+1,length(Ext)}.
+extensible_dec({RootList,ExtList}) ->
+ {ext,length(RootList)+1,ext_length(ExtList)};
+extensible_dec({Rl1,Ext,Rl2}) ->
+ {ext,length(Rl1)+length(Rl2)+1,ext_length(Ext)}.
+
+extensible_enc(CompList) when is_list(CompList) ->
+ noext;
+extensible_enc({RootList,ExtList}) ->
+ {ext,length(RootList)+1,ext_length(ExtList)};
+extensible_enc({Rl1,Ext,_Rl2}) ->
+ {ext,length(Rl1)+1,ext_length(Ext)}.
+
+ext_length(ExtList) -> ext_length(ExtList,normal,0).
+ext_length([{'ExtensionAdditionGroup',_Num}|T],_,Acc)->
+ ext_length(T,group,Acc);
+ext_length(['ExtensionAdditionGroupEnd'|T],group,Acc) ->
+ ext_length(T,normal,Acc+1);
+ext_length([#'ComponentType'{}|T],State=group,Acc) ->
+ ext_length(T,State,Acc);
+ext_length([#'ComponentType'{}|T],State=normal,Acc) ->
+ ext_length(T,State,Acc+1);
+ext_length([],_,Acc) ->
+ Acc.
+
+extgroup_pos_and_length(CompList) when is_list(CompList) ->
+ noextgroup;
+extgroup_pos_and_length({RootList,ExtList}) ->
+ extgrouppos(ExtList,length(RootList)+1);
+extgroup_pos_and_length({Rl1,Ext,_Rl2}) ->
+ extgrouppos(Ext,length(Rl1)+1).
+
+extgrouppos([{'ExtensionAdditionGroup',_Num}|T],Pos) ->
+ extgrouppos(T,Pos,0);
+extgrouppos([_|T],Pos) ->
+ extgrouppos(T,Pos+1);
+extgrouppos([],_) ->
+ noextgroup.
+
+extgrouppos(['ExtensionAdditionGroupEnd'|_T],Pos,Len) ->
+ {extgrouppos,Pos,Len};
+extgrouppos([_|T],Pos,Len) ->
+ extgrouppos(T,Pos,Len+1).
+
+
gen_dec_extension_value(_) ->
emit({"{Ext,",{next,bytes},"} = ?RT_PER:getext(",{curr,bytes},")"}),
@@ -574,7 +643,11 @@ gen_dec_extension_value(_) ->
%% there are optional components, start with 2 because first element
%% is the record name
-optionals({L1,_Ext,L2}) -> optionals(L1++L2,[],2);
+optionals({L1,Ext,L2}) ->
+ Opt1 = optionals(L1,[],2),
+ ExtComps = length([C||C = #'ComponentType'{}<-Ext]),
+ Opt2 = optionals(L2,[],2+length(L1)+ExtComps),
+ Opt1 ++ Opt2;
optionals({L,_Ext}) -> optionals(L,[],2);
optionals(L) -> optionals(L,[],2).
@@ -617,6 +690,13 @@ get_optionality_pos(TextPos,OptTable) ->
no_num
end.
+to_encoding_order(Cs) when is_list(Cs) ->
+ Cs;
+to_encoding_order(Cs = {_Root,_Ext}) ->
+ Cs;
+to_encoding_order({R1,Ext,R2}) ->
+ {R1++R2,Ext}.
+
add_textual_order(Cs) when is_list(Cs) ->
{NewCs,_} = add_textual_order1(Cs,1),
NewCs;
@@ -629,26 +709,20 @@ add_textual_order({R1,Ext,R2}) ->
{NewExt,Num2} = add_textual_order1(Ext,Num1),
{NewR2,_} = add_textual_order1(R2,Num2),
{NewR1,NewExt,NewR2}.
-add_textual_order1(Cs=[#'ComponentType'{textual_order=Int}|_],I)
- when is_integer(Int) ->
- {Cs,I};
+%%add_textual_order1(Cs=[#'ComponentType'{textual_order=Int}|_],I)
+%% when is_integer(Int) ->
+%% {Cs,I};
add_textual_order1(Cs,NumIn) ->
- lists:mapfoldl(fun(C,Num) ->
+ lists:mapfoldl(fun(C=#'ComponentType'{},Num) ->
{C#'ComponentType'{textual_order=Num},
- Num+1}
+ Num+1};
+ (OtherMarker,Num) ->
+ {OtherMarker,Num}
end,
NumIn,Cs).
gen_enc_components_call(Erule,TopType,{Root1,ExtList,Root2},MaybeComma,DynamicEnc,Ext) ->
- Rpos = gen_enc_components_call1(Erule,TopType,Root1,1,MaybeComma,DynamicEnc,noext),
- case Ext of
- {ext,_,ExtNum} when ExtNum > 0 ->
- emit([nl,
- ",Extensions",nl]);
- _ -> true
- end,
- Rpos2 = gen_enc_components_call1(Erule,TopType,ExtList,Rpos,MaybeComma,DynamicEnc,Ext),
- gen_enc_components_call1(Erule,TopType,Root2,Rpos2,MaybeComma,DynamicEnc,noext);
+ gen_enc_components_call(Erule,TopType,{Root1++Root2,ExtList},MaybeComma,DynamicEnc,Ext);
gen_enc_components_call(Erule,TopType,{CompList,ExtList},MaybeComma,DynamicEnc,Ext) ->
%% The type has extensionmarker
Rpos = gen_enc_components_call1(Erule,TopType,CompList,1,MaybeComma,DynamicEnc,noext),
@@ -659,7 +733,8 @@ gen_enc_components_call(Erule,TopType,{CompList,ExtList},MaybeComma,DynamicEnc,E
_ -> true
end,
%handle extensions
- gen_enc_components_call1(Erule,TopType,ExtList,Rpos,MaybeComma,DynamicEnc,Ext);
+ NewExtList = wrap_extensionAdditionGroups(ExtList),
+ gen_enc_components_call1(Erule,TopType,NewExtList,Rpos,MaybeComma,DynamicEnc,Ext);
gen_enc_components_call(Erule,TopType, CompList, MaybeComma, DynamicEnc, Ext) ->
%% The type has no extensionmarker
gen_enc_components_call1(Erule,TopType,CompList,1,MaybeComma,DynamicEnc,Ext).
@@ -706,7 +781,7 @@ gen_enc_components_call1(_Erule,_TopType,[],Pos,_,_,_) ->
Pos.
gen_enc_component_default(Erule,TopType,Cname,Type,Pos,DynamicEnc,Ext,DefaultVal) ->
- Element = make_element(Pos+1,"Val1",Cname),
+ Element = make_element(Pos+1,asn1ct_gen:mk_var(asn1ct_name:curr(val)),Cname),
emit({"case ",Element," of",nl}),
% emit({"asn1_DEFAULT -> [];",nl}),
emit({"DFLT when DFLT == asn1_DEFAULT; DFLT == ",{asis,DefaultVal}," -> [];",nl}),
@@ -719,8 +794,27 @@ gen_enc_component_default(Erule,TopType,Cname,Type,Pos,DynamicEnc,Ext,DefaultVal
NextElement = asn1ct_gen:mk_var(asn1ct_name:curr(tmpval)),
gen_enc_line(Erule,TopType,Cname,Type,NextElement, Pos,DynamicEnc,Ext),
emit({nl,"end"}).
+
+gen_enc_component_optional(Erule,TopType,Cname,
+ Type=#type{def=#'SEQUENCE'{
+ extaddgroup=Number,
+ components=_ExtGroupCompList}},
+ Pos,DynamicEnc,Ext) when is_integer(Number) ->
+
+ Element = make_element(Pos+1,asn1ct_gen:mk_var(asn1ct_name:curr(val)),Cname),
+ emit({"case ",Element," of",nl}),
+
+ emit({"asn1_NOVALUE -> [];",nl}),
+ asn1ct_name:new(tmpval),
+ emit({{curr,tmpval}," ->",nl}),
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ emit({nl,"%% attribute number ",Pos," with type ",
+ InnerType,nl}),
+ NextElement = asn1ct_gen:mk_var(asn1ct_name:curr(tmpval)),
+ gen_enc_line(Erule,TopType,Cname,Type,NextElement, Pos,DynamicEnc,Ext),
+ emit({nl,"end"});
gen_enc_component_optional(Erule,TopType,Cname,Type,Pos,DynamicEnc,Ext) ->
- Element = make_element(Pos+1,"Val1",Cname),
+ Element = make_element(Pos+1,asn1ct_gen:mk_var(asn1ct_name:curr(val)),Cname),
emit({"case ",Element," of",nl}),
emit({"asn1_NOVALUE -> [];",nl}),
@@ -834,29 +928,7 @@ gen_enc_line(Erule,TopType,Cname,Type,Element, _Pos,DynamicEnc,Ext) ->
_ -> true
end.
gen_dec_components_call(Erule,TopType,{Root1,ExtList,Root2},MaybeComma,DecInfObj,Ext,NumberOfOptionals) ->
- %% The type has extensionmarker
- OptTable = create_optionality_table(Root1 ++ Root2),
- {Rpos,AccTerm,AccBytes} =
- gen_dec_components_call1(Erule,TopType, Root1, 1, OptTable,
- MaybeComma,DecInfObj, noext,[],[],
- NumberOfOptionals),
- emit([",",nl,"{Extensions,",{next,bytes},"} = "]),
- emit(["?RT_PER:getextension(Ext,",{curr,bytes},"),",nl]),
- asn1ct_name:new(bytes),
- {Epos,AccTermE,AccBytesE} =
- gen_dec_components_call1(Erule,TopType,ExtList,Rpos, OptTable, "",
- DecInfObj,Ext,[],[],NumberOfOptionals),
- case ExtList of
- [] -> true;
- _ -> emit([",",nl])
- end,
- emit([{next,bytes},"= ?RT_PER:skipextensions(",{curr,bytes},",",
- length(ExtList)+1,",Extensions),",nl]),
- asn1ct_name:new(bytes),
- {_RPos2,AccTerm2,AccBytes2} =
- gen_dec_components_call1(Erule,TopType,Root2,Epos,OptTable,
- "",DecInfObj,noext,[],[],NumberOfOptionals),
- {AccTerm++AccTermE++AccTerm2,AccBytes++AccBytesE++AccBytes2};
+ gen_dec_components_call(Erule,TopType,{Root1++Root2,ExtList},MaybeComma,DecInfObj,Ext,NumberOfOptionals);
gen_dec_components_call(Erule,TopType,{CompList,ExtList},MaybeComma,
DecInfObj,Ext,NumberOfOptionals) ->
%% The type has extensionmarker
@@ -868,8 +940,9 @@ gen_dec_components_call(Erule,TopType,{CompList,ExtList},MaybeComma,
emit([",",nl,"{Extensions,",{next,bytes},"} = "]),
emit(["?RT_PER:getextension(Ext,",{curr,bytes},"),",nl]),
asn1ct_name:new(bytes),
+ NewExtList = wrap_extensionAdditionGroups(ExtList),
{_Epos,AccTermE,AccBytesE} =
- gen_dec_components_call1(Erule,TopType,ExtList,Rpos, OptTable,
+ gen_dec_components_call1(Erule,TopType,NewExtList,Rpos, OptTable,
"",DecInfObj,Ext,[],[],NumberOfOptionals),
case ExtList of
[] -> true;
@@ -942,8 +1015,18 @@ gen_dec_components_call1(Erule,TopType,
asn1ct_name:new(tmpterm),
emit({"{",{curr,tmpterm},", ",{next,bytes},"} = "});
_ ->
- asn1ct_name:new(term),
- emit({"{",{curr,term},",",{next,bytes},"} = "})
+ case Type of
+ #type{def=#'SEQUENCE'{
+ extaddgroup=Number1,
+ components=ExtGroupCompList1}} when is_integer(Number1)->
+ emit({"{{_,"}),
+ emit_extaddgroupTerms(term,ExtGroupCompList1),
+ emit({"}"});
+ _ ->
+ asn1ct_name:new(term),
+ emit({"{",{curr,term}})
+ end,
+ emit({",",{next,bytes},"} = "})
end,
case {Ext,Prop,is_optimized(Erule)} of
@@ -967,11 +1050,24 @@ gen_dec_components_call1(Erule,TopType,
{noext,mandatory} -> true; % generate nothing
{noext,_} ->
emit([";",nl,"0 ->"]),
- gen_dec_component_no_val(TopType,Cname,Type,Prop,Tpos,Ext),
+ emit(["{"]),
+ gen_dec_component_no_val(Ext,Prop),
+ emit({",",{curr,bytes},"}",nl}),
emit([nl,"end"]);
_ ->
emit([";",nl,"_ ->",nl]),
- gen_dec_component_no_val(TopType,Cname,Type,Prop,Tpos,Ext),
+ emit(["{"]),
+ case Type of
+ #type{def=#'SEQUENCE'{
+ extaddgroup=Number2,
+ components=ExtGroupCompList2}} when is_integer(Number2)->
+ emit({"{extAddGroup,"}),
+ gen_dec_extaddGroup_no_val(Ext,ExtGroupCompList2),
+ emit({"}"});
+ _ ->
+ gen_dec_component_no_val(Ext,Prop)
+ end,
+ emit({",",{curr,bytes},"}",nl}),
emit([nl,"end"])
end,
asn1ct_name:new(bytes),
@@ -988,13 +1084,22 @@ gen_dec_components_call1(Erule,TopType,
gen_dec_components_call1(_,_TopType,[],Pos,_OptTable,_,_,_,AccTerm,AccBytes,_NumberOfOptionals) ->
{Pos,AccTerm,AccBytes}.
-
-gen_dec_component_no_val(_,_,_,{'DEFAULT',DefVal},_,_) ->
- emit(["{",{asis,DefVal},",",{curr,bytes},"}",nl]);
-gen_dec_component_no_val(_,_,_,'OPTIONAL',_,_) ->
- emit({"{asn1_NOVALUE,",{curr,bytes},"}",nl});
-gen_dec_component_no_val(_,_,_,mandatory,_,{ext,_,_}) ->
- emit({"{asn1_NOVALUE,",{curr,bytes},"}",nl}).
+gen_dec_extaddGroup_no_val(Ext,[#'ComponentType'{prop=Prop}])->
+ gen_dec_component_no_val(Ext,Prop),
+ ok;
+gen_dec_extaddGroup_no_val(Ext,[#'ComponentType'{prop=Prop}|Rest])->
+ gen_dec_component_no_val(Ext,Prop),
+ emit({","}),
+ gen_dec_extaddGroup_no_val(Ext,Rest);
+gen_dec_extaddGroup_no_val(_, []) ->
+ ok.
+
+gen_dec_component_no_val(_,{'DEFAULT',DefVal}) ->
+ emit([{asis,DefVal}]);
+gen_dec_component_no_val(_,'OPTIONAL') ->
+ emit({"asn1_NOVALUE"});
+gen_dec_component_no_val({ext,_,_},mandatory) ->
+ emit({"asn1_NOVALUE"}).
gen_dec_line(Erule,TopType,Cname,Type,Pos,DecInfObj,Ext,Prop) ->
@@ -1192,6 +1297,14 @@ gen_enc_choice_tag({C1,C2},_,_) ->
N2 = get_name_list(C2),
emit(["?RT_PER:set_choice(element(1,Val),",
{asis,{N1,N2}},", ",{asis,{length(N1),length(N2)}},")"]);
+
+gen_enc_choice_tag({C1,C2,C3},_,_) ->
+ N1 = get_name_list(C1),
+ N2 = get_name_list(C2),
+ N3 = get_name_list(C3),
+ Root = N1 ++ N3,
+ emit(["?RT_PER:set_choice(element(1,Val),",
+ {asis,{Root,N2}},", ",{asis,{length(Root),length(N2)}},")"]);
gen_enc_choice_tag(C,_,_) ->
N = get_name_list(C),
emit(["?RT_PER:set_choice(element(1,Val),",
@@ -1208,6 +1321,8 @@ get_name_list([], Acc) ->
gen_enc_choice2(Erule,TopType, {L1,L2}, Ext) ->
gen_enc_choice2(Erule,TopType, L1 ++ L2, 0, Ext);
+gen_enc_choice2(Erule,TopType, {L1,L2,L3}, Ext) ->
+ gen_enc_choice2(Erule,TopType, L1 ++ L3 ++ L2, 0, Ext);
gen_enc_choice2(Erule,TopType, L, Ext) ->
gen_enc_choice2(Erule,TopType, L, 0, Ext).
@@ -1279,6 +1394,9 @@ gen_dec_choice1(Erule,TopType,CompList,noext) ->
gen_dec_choice1(Erule,TopType,{RootList,ExtList},Ext) ->
NewList = RootList ++ ExtList,
gen_dec_choice1(Erule,TopType, NewList, Ext);
+gen_dec_choice1(Erule,TopType,{RootList,ExtList,RootList2},Ext) ->
+ NewList = RootList ++ RootList2 ++ ExtList,
+ gen_dec_choice1(Erule,TopType, NewList, Ext);
gen_dec_choice1(Erule,TopType,CompList,{ext,ExtPos,ExtNum}) ->
emit({"{Choice,",{curr,bytes},
"} = ?RT_PER:getchoice(",{prev,bytes},",",
@@ -1347,6 +1465,18 @@ gen_encode_prim_wrapper(CtgenMod,Erule,Cont,DoTag,Value) ->
CtgenMod:gen_encode_prim(Erule,Cont,DoTag,Value).
% erase(component_type).
+make_elements(I,Val,ExtCnames) ->
+ make_elements(I,Val,ExtCnames,[]).
+
+make_elements(I,Val,[ExtCname],Acc)-> % the last one, no comma needed
+ Element = make_element(I,Val,ExtCname),
+ make_elements(I+1,Val,[],[Element|Acc]);
+make_elements(I,Val,[ExtCname|Rest],Acc)->
+ Element = make_element(I,Val,ExtCname),
+ make_elements(I+1,Val,Rest,[", ",Element|Acc]);
+make_elements(_I,_,[],Acc) ->
+ lists:reverse(Acc).
+
make_element(I,Val,Cname) ->
case tuple_notation_allowed() of
true ->
@@ -1355,6 +1485,55 @@ make_element(I,Val,Cname) ->
io_lib:format("element(~w,~s)",[I,Val])
end.
+emit_extaddgroupTerms(VarSeries,[_]) ->
+ asn1ct_name:new(VarSeries),
+ emit({curr,VarSeries}),
+ ok;
+emit_extaddgroupTerms(VarSeries,[_|Rest]) ->
+ asn1ct_name:new(VarSeries),
+ emit({{curr,VarSeries},","}),
+ emit_extaddgroupTerms(VarSeries,Rest);
+emit_extaddgroupTerms(_,[]) ->
+ ok.
+wrap_compList({Root1,Ext,Root2}) ->
+ {Root1,wrap_extensionAdditionGroups(Ext),Root2};
+wrap_compList({Root1,Ext}) ->
+ {Root1,wrap_extensionAdditionGroups(Ext)};
+wrap_compList(CompList) ->
+ CompList.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Will convert all componentTypes following 'ExtensionAdditionGroup'
+%% up to the matching 'ExtensionAdditionGroupEnd' into one componentType
+%% of type SEQUENCE with the componentTypes as components
+%%
+wrap_extensionAdditionGroups(ExtCompList) ->
+ wrap_extensionAdditionGroups(ExtCompList,[],0).
+
+wrap_extensionAdditionGroups([{'ExtensionAdditionGroup',_Number}|Rest],Acc,0) ->
+ {ExtGroupCompList=
+ [#'ComponentType'{textual_order=TextPos}|_],
+ ['ExtensionAdditionGroupEnd'|Rest2]} =
+ lists:splitwith(fun(#'ComponentType'{}) -> true;
+ (_) -> false
+ end,
+ Rest),
+ wrap_extensionAdditionGroups(Rest2,
+ [#'ComponentType'{
+ name='ExtAddGroup', % FIXME: handles ony one ExtAddGroup
+ typespec=#type{def=#'SEQUENCE'{
+ extaddgroup=1,% FIXME: handles only one
+ components=ExtGroupCompList}},
+ textual_order = TextPos,
+ prop='OPTIONAL'}|Acc],length(ExtGroupCompList)-1);
+wrap_extensionAdditionGroups([H=#'ComponentType'{textual_order=Tord}|T],Acc,ExtAddGroupDiff) when is_integer(Tord) ->
+ wrap_extensionAdditionGroups(T,[H#'ComponentType'{
+ textual_order=Tord - ExtAddGroupDiff}|Acc],ExtAddGroupDiff);
+wrap_extensionAdditionGroups([H|T],Acc,ExtAddGroupDiff) ->
+ wrap_extensionAdditionGroups(T,[H|Acc],ExtAddGroupDiff);
+wrap_extensionAdditionGroups([],Acc,_) ->
+ lists:reverse(Acc).
+
+
tuple_notation_allowed() ->
Options = get(encoding_options),
not (lists:member(optimize,Options) orelse lists:member(uper_bin,Options)).
diff --git a/lib/asn1/src/asn1ct_gen.erl b/lib/asn1/src/asn1ct_gen.erl
index eab5fb4a2a..0bb0b65e5d 100644
--- a/lib/asn1/src/asn1ct_gen.erl
+++ b/lib/asn1/src/asn1ct_gen.erl
@@ -536,14 +536,19 @@ gen_part_decode_funcs({primitive,bif},_TypeName,
gen_part_decode_funcs(WhatKind,_TypeName,{_,Directive,_,_}) ->
throw({error,{asn1,{"Not implemented yet",WhatKind," partial incomplete directive:",Directive}}}).
+
gen_types(Erules,Tname,{RootL1,ExtList,RootL2})
when is_list(RootL1), is_list(RootL2) ->
gen_types(Erules,Tname,RootL1),
- gen_types(Erules,Tname,ExtList),
+ Rtmod = list_to_atom(lists:concat(["asn1ct_gen_",erule(Erules),
+ rt2ct_suffix(Erules)])),
+ gen_types(Erules,Tname,Rtmod:extaddgroup2sequence(ExtList)),
gen_types(Erules,Tname,RootL2);
gen_types(Erules,Tname,{RootList,ExtList}) when is_list(RootList) ->
gen_types(Erules,Tname,RootList),
- gen_types(Erules,Tname,ExtList);
+ Rtmod = list_to_atom(lists:concat(["asn1ct_gen_",erule(Erules),
+ rt2ct_suffix(Erules)])),
+ gen_types(Erules,Tname,Rtmod:extaddgroup2sequence(ExtList));
gen_types(Erules,Tname,[{'EXTENSIONMARK',_,_}|Rest]) ->
gen_types(Erules,Tname,Rest);
gen_types(Erules,Tname,[ComponentType|Rest]) ->
@@ -1543,19 +1548,18 @@ gen_record2(Name,SeqOrSet,Comps) ->
gen_record2(_Name,_SeqOrSet,[],_Com,_Extension) ->
true;
-gen_record2(Name,SeqOrSet,[{'EXTENSIONMARK',_,_}|T],Com,Extension) ->
- gen_record2(Name,SeqOrSet,T,Com,Extension);
-gen_record2(_Name,_SeqOrSet,[H],Com,Extension) ->
- #'ComponentType'{name=Cname} = H,
+gen_record2(_Name,_SeqOrSet,[H = #'ComponentType'{name=Cname}],Com,Extension) ->
emit(Com),
emit({asis,Cname}),
gen_record_default(H, Extension);
-gen_record2(Name,SeqOrSet,[H|T],Com, Extension) ->
- #'ComponentType'{name=Cname} = H,
+gen_record2(Name,SeqOrSet,[H = #'ComponentType'{name=Cname}|T],Com, Extension) ->
emit(Com),
emit({asis,Cname}),
gen_record_default(H, Extension),
- gen_record2(Name,SeqOrSet,T,", ", Extension).
+ gen_record2(Name,SeqOrSet,T,", ", Extension);
+gen_record2(Name,SeqOrSet,[_|T],Com,Extension) ->
+ %% skip EXTENSIONMARK, ExtensionAdditionGroup and other markers
+ gen_record2(Name,SeqOrSet,T,Com,Extension).
gen_record_default(#'ComponentType'{prop='OPTIONAL'}, _)->
emit(" = asn1_NOVALUE");
diff --git a/lib/asn1/src/asn1ct_gen_ber.erl b/lib/asn1/src/asn1ct_gen_ber.erl
index d70586c75c..491ebcb8fd 100644
--- a/lib/asn1/src/asn1ct_gen_ber.erl
+++ b/lib/asn1/src/asn1ct_gen_ber.erl
@@ -33,6 +33,7 @@
-export([gen_objectset_code/2, gen_obj_code/3]).
-export([re_wrap_erule/1]).
-export([unused_var/2]).
+-export([extaddgroup2sequence/1]).
-import(asn1ct_gen, [emit/1,demit/1]).
@@ -1734,3 +1735,15 @@ get_object_field(Name,ObjectFields) ->
{value,Field} -> Field;
false -> false
end.
+
+%% For BER the ExtensionAdditionGroup notation has no impact on the encoding/decoding
+%% and therefore we only filter away the ExtensionAdditionGroup start and end markers
+%%
+extaddgroup2sequence(ExtList) when is_list(ExtList) ->
+ lists:filter(fun(#'ExtensionAdditionGroup'{}) ->
+ false;
+ ('ExtensionAdditionGroupEnd') ->
+ false;
+ (_) ->
+ true
+ end, ExtList).
diff --git a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
index a146e92d64..9ec458e351 100644
--- a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
+++ b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
@@ -33,6 +33,7 @@
-export([gen_objectset_code/2, gen_obj_code/3]).
-export([encode_tag_val/3]).
-export([gen_inc_decode/2,gen_decode_selected/3]).
+-export([extaddgroup2sequence/1]).
-import(asn1ct_gen, [emit/1,demit/1]).
@@ -1826,8 +1827,15 @@ mk_object_val(Val, Ack, Len) ->
add_func(F={_Func,_Arity}) ->
ets:insert(asn1_functab,{F}).
-
-
-
+%% For BER the ExtensionAdditionGroup notation has no impact on the encoding/decoding
+%% and therefore we only filter away the ExtensionAdditionGroup start and end markers
+extaddgroup2sequence(ExtList) when is_list(ExtList) ->
+ lists:filter(fun(#'ExtensionAdditionGroup'{}) ->
+ false;
+ ('ExtensionAdditionGroupEnd') ->
+ false;
+ (_) ->
+ true
+ end, ExtList).
diff --git a/lib/asn1/src/asn1ct_gen_per.erl b/lib/asn1/src/asn1ct_gen_per.erl
index 23fb392d60..8313cf1b60 100644
--- a/lib/asn1/src/asn1ct_gen_per.erl
+++ b/lib/asn1/src/asn1ct_gen_per.erl
@@ -31,6 +31,7 @@
-export([gen_encode/2, gen_encode/3]).
-export([is_already_generated/2,more_genfields/1,get_class_fields/1,
get_object_field/2]).
+-export([extaddgroup2sequence/1]).
-import(asn1ct_gen, [emit/1,demit/1]).
@@ -1393,3 +1394,25 @@ get_object_field(Name,ObjectFields) ->
false -> false
end.
+
+%% For PER the ExtensionAdditionGroup notation has significance for the encoding and decoding
+%% the components within the ExtensionAdditionGroup is treated in a similar way as if they
+%% have been specified within a SEQUENCE, therefore we construct a fake sequence type here
+%% so that we can generate code for it
+extaddgroup2sequence(ExtList) ->
+ extaddgroup2sequence(ExtList,[]).
+
+extaddgroup2sequence([{'ExtensionAdditionGroup',Number0}|T],Acc) ->
+ Number = case Number0 of undefined -> 1; _ -> Number0 end,
+ {ExtGroupComps,['ExtensionAdditionGroupEnd'|T2]} =
+ lists:splitwith(fun(Elem) -> is_record(Elem,'ComponentType') end,T),
+ extaddgroup2sequence(T2,[#'ComponentType'{
+ name='ExtAddGroup',
+ typespec=#type{def=#'SEQUENCE'{
+ extaddgroup=Number,
+ components=ExtGroupComps}},
+ prop='OPTIONAL'}|Acc]);
+extaddgroup2sequence([C|T],Acc) ->
+ extaddgroup2sequence(T,[C|Acc]);
+extaddgroup2sequence([],Acc) ->
+ lists:reverse(Acc).
diff --git a/lib/asn1/src/asn1ct_gen_per_rt2ct.erl b/lib/asn1/src/asn1ct_gen_per_rt2ct.erl
index e1feb42a59..4f4fcfafc3 100644
--- a/lib/asn1/src/asn1ct_gen_per_rt2ct.erl
+++ b/lib/asn1/src/asn1ct_gen_per_rt2ct.erl
@@ -29,6 +29,7 @@
-export([gen_obj_code/3,gen_objectset_code/2]).
-export([gen_decode/2, gen_decode/3]).
-export([gen_encode/2, gen_encode/3]).
+-export([extaddgroup2sequence/1]).
-import(asn1ct_gen, [emit/1,demit/1]).
-import(asn1ct_gen_per, [is_already_generated/2,more_genfields/1,
@@ -1796,3 +1797,25 @@ dec_enumerated_cases([Name|Rest],Tmpremain,No) ->
dec_enumerated_cases(Rest,Tmpremain,No+1);
dec_enumerated_cases([],_,_) ->
"".
+
+%% For PER the ExtensionAdditionGroup notation has significance for the encoding and decoding
+%% the components within the ExtensionAdditionGroup is treated in a similar way as if they
+%% have been specified within a SEQUENCE, therefore we construct a fake sequence type here
+%% so that we can generate code for it
+extaddgroup2sequence(ExtList) ->
+ extaddgroup2sequence(ExtList,[]).
+
+extaddgroup2sequence([{'ExtensionAdditionGroup',Number0}|T],Acc) ->
+ Number = case Number0 of undefined -> 1; _ -> Number0 end,
+ {ExtGroupComps,['ExtensionAdditionGroupEnd'|T2]} =
+ lists:splitwith(fun(Elem) -> is_record(Elem,'ComponentType') end,T),
+ extaddgroup2sequence(T2,[#'ComponentType'{
+ name='ExtAddGroup',
+ typespec=#type{def=#'SEQUENCE'{
+ extaddgroup=Number,
+ components=ExtGroupComps}},
+ prop='OPTIONAL'}|Acc]);
+extaddgroup2sequence([C|T],Acc) ->
+ extaddgroup2sequence(T,[C|Acc]);
+extaddgroup2sequence([],Acc) ->
+ lists:reverse(Acc).
diff --git a/lib/asn1/src/asn1ct_parser2.erl b/lib/asn1/src/asn1ct_parser2.erl
index 46d7ad6fdb..224a535e87 100644
--- a/lib/asn1/src/asn1ct_parser2.erl
+++ b/lib/asn1/src/asn1ct_parser2.erl
@@ -417,10 +417,22 @@ parse_BuiltinType([{'CHARACTER',_},{'STRING',_}|Rest]) ->
{#type{def='CHARACTER STRING'},Rest};
parse_BuiltinType([{'CHOICE',_},{'{',_}|Rest]) ->
- {AlternativeTypeLists,Rest2} = parse_AlternativeTypeLists(Rest,get(extensiondefault)),
+ {AlternativeTypeLists,Rest2} = parse_AlternativeTypeLists(Rest),
+ AlternativeTypeLists1 =
+ lists:filter(fun(#'ExtensionAdditionGroup'{}) -> false;
+ ('ExtensionAdditionGroupEnd') -> false;
+ (_) -> true
+ end,AlternativeTypeLists),
case Rest2 of
[{'}',_}|Rest3] ->
- {#type{def={'CHOICE',AlternativeTypeLists}},Rest3};
+ AlternativeTypeLists2 =
+ case {[Ext||Ext = #'EXTENSIONMARK'{} <- AlternativeTypeLists1],
+ get(extensiondefault)} of
+ {[],'IMPLIED'} -> AlternativeTypeLists1 ++ [#'EXTENSIONMARK'{}];
+ _ -> AlternativeTypeLists1
+ end,
+
+ {#type{def={'CHOICE',AlternativeTypeLists2}},Rest3};
_ ->
throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
[got,get_token(hd(Rest2)),expected,'}']}})
@@ -479,16 +491,19 @@ parse_BuiltinType([{'REAL',_}|Rest]) ->
{#type{def='REAL'},Rest};
parse_BuiltinType([{'RELATIVE-OID',_}|Rest]) ->
{#type{def='RELATIVE-OID'},Rest};
-parse_BuiltinType([{'SEQUENCE',_},{'{',_},{'...',Line},{'}',_}|Rest]) ->
- {#type{def=#'SEQUENCE'{components=[{'EXTENSIONMARK',Line,undefined}]}},
+parse_BuiltinType([{'SEQUENCE',_},{'{',_},{'}',_}|Rest]) ->
+ {#type{def=#'SEQUENCE'{components=[]}},
Rest};
+parse_BuiltinType([{'SEQUENCE',_},{'{',_},{'...',Line},{'}',_}|Rest]) ->
+ {#type{def=#'SEQUENCE'{components=[#'EXTENSIONMARK'{pos = Line}]}},Rest};
parse_BuiltinType([{'SEQUENCE',_},{'{',_},{'...',Line},{'!',_}|Rest]) ->
{ExceptionIdentification,Rest2} = parse_ExceptionIdentification(Rest),
case Rest2 of
[{'}',_}|Rest3] ->
- {#type{def=#'SEQUENCE'{components=[{'EXTENSIONMARK',
- Line,
- ExceptionIdentification}]}},
+ {#type{def=#'SEQUENCE'{
+ components=[#'EXTENSIONMARK'{
+ pos = Line,
+ val = ExceptionIdentification}]}},
Rest3};
_ ->
{ComponentTypeLists,Rest3}=
@@ -537,13 +552,14 @@ parse_BuiltinType([{'SEQUENCE',_},{'OF',_}|Rest]) ->
parse_BuiltinType([{'SET',_},{'{',_},{'...',Line},{'}',_}|Rest]) ->
- {#type{def=#'SET'{components=[{'EXTENSIONMARK',Line,undefined}]}},Rest};
+ {#type{def=#'SET'{components=[#'EXTENSIONMARK'{pos = Line}]}},Rest};
parse_BuiltinType([{'SET',_},{'{',_},{'...',Line},{'!',_}|Rest]) ->
{ExceptionIdentification,Rest2} = parse_ExceptionIdentification(Rest),
case Rest2 of
[{'}',_}|Rest3] ->
{#type{def=#'SET'{components=
- [{'EXTENSIONMARK',Line,ExceptionIdentification}]}},
+ [#'EXTENSIONMARK'{pos = Line,
+ val = ExceptionIdentification}]}},
Rest3};
_ ->
throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
@@ -2323,101 +2339,197 @@ to_set(V) when is_list(V) ->
to_set(V) ->
ordsets:from_list([V]).
+parse_AlternativeTypeLists(Tokens) ->
+ parse_AlternativeTypeLists(Tokens,[]).
-parse_AlternativeTypeLists(Tokens,ExtensionDefault) ->
- {AltTypeList,Rest1} = parse_AlternativeTypeList(Tokens),
- {ExtensionAndException,Rest2} =
- case Rest1 of
- [{',',_},{'...',L1},{'!',_}|Rest12] ->
- {_,Rest13} = parse_ExceptionIdentification(Rest12),
- %% Exception info is currently thrown away
- {[#'EXTENSIONMARK'{pos=L1}],Rest13};
- [{',',_},{'...',L1}|Rest12] ->
- {[#'EXTENSIONMARK'{pos=L1}],Rest12};
- _ ->
- {[],Rest1}
- end,
- {AltTypeList2,Rest5} =
- case ExtensionAndException of
- [] ->
- {AltTypeList,Rest2};
- _ ->
- {ExtensionAddition,Rest3} =
- case Rest2 of
- [{',',_}|Rest23] ->
- parse_ExtensionAdditionAlternativeList(Rest23);
- _ ->
- {[],Rest2}
- end,
- {OptionalExtensionMarker,Rest4} =
- case Rest3 of
- [{',',_},{'...',L3}|Rest31] ->
- {[#'EXTENSIONMARK'{pos=L3}],Rest31};
- _ ->
- {[],Rest3}
- end,
- {AltTypeList ++ ExtensionAndException ++
- ExtensionAddition ++ OptionalExtensionMarker, Rest4}
- end,
- AltTypeList3 =
- case [X || X=#'EXTENSIONMARK'{} <- AltTypeList2] of
- [] when ExtensionDefault == 'IMPLIED' ->
- AltTypeList2 ++ [#'EXTENSIONMARK'{}];
- _ ->
- AltTypeList2
- end,
- {AltTypeList3,Rest5}.
-
+parse_AlternativeTypeLists(Tokens = [{identifier,_,_}|_Rest0],Clist) ->
+ {CompList,Rest1} = parse_AlternativeTypeList(Tokens,[]),
+ parse_AlternativeTypeLists(Rest1,Clist++CompList);
+parse_AlternativeTypeLists([{'...',L1},{'!',_}|Rest02],Clist0) ->
+ {_,Rest03} = parse_ExceptionIdentification(Rest02),
+ %% Exception info is currently thrown away
+ parse_AlternativeTypeLists2(Rest03,Clist0++[#'EXTENSIONMARK'{pos=L1}]);
+parse_AlternativeTypeLists([{',',L1},{'...',_},{'!',_}|Rest02],Clist0) when Clist0 =/= []->
+ {_,Rest03} = parse_ExceptionIdentification(Rest02),
+ %% Exception info is currently thrown away
+ parse_AlternativeTypeLists2(Rest03,Clist0++[#'EXTENSIONMARK'{pos=L1}]);
+
+parse_AlternativeTypeLists([{',',_},{'...',L1}|Rest02],Clist0) when Clist0 =/= []->
+ parse_AlternativeTypeLists2(Rest02,Clist0++[#'EXTENSIONMARK'{pos=L1}]);
+parse_AlternativeTypeLists([{'...',L1}|Rest02],Clist0) ->
+ parse_AlternativeTypeLists2(Rest02,Clist0++[#'EXTENSIONMARK'{pos=L1}]);
+parse_AlternativeTypeLists(Tokens = [{'}',_L1}|_Rest02],Clist0) ->
+ {Clist0,Tokens}.
+
+parse_AlternativeTypeLists2(Tokens,Clist) ->
+ {ExtAdd,Rest} = parse_ExtensionAdditionAlternatives(Tokens,Clist),
+ {Clist2,Rest2} = parse_OptionalExtensionMarker(Rest,lists:flatten(ExtAdd)),
+ case Rest2 of
+ [{',',_}|Rest3] ->
+ {CompList,Rest4} = parse_AlternativeTypeList(Rest3,[]),
+ {Clist2 ++ CompList,Rest4};
+ _ ->
+ {Clist2,Rest2}
+ end.
-parse_AlternativeTypeList(Tokens) ->
- parse_AlternativeTypeList(Tokens,[]).
-parse_AlternativeTypeList(Tokens,Acc) ->
- {NamedType,Rest} = parse_NamedType(Tokens),
+
+parse_AlternativeTypeList([{',',_},Id = {identifier,_,_}|Rest],Acc) when Acc =/= [] ->
+ {AlternativeType,Rest2} = parse_NamedType([Id|Rest]),
+ parse_AlternativeTypeList(Rest2,[AlternativeType|Acc]);
+parse_AlternativeTypeList(Tokens = [{'}',_}|_],Acc) ->
+ {lists:reverse(Acc),Tokens};
+parse_AlternativeTypeList(Tokens = [{']',_},{']',_}|_],Acc) ->
+ {lists:reverse(Acc),Tokens};
+parse_AlternativeTypeList(Tokens = [{',',_},{'...',_}|_],Acc) ->
+ {lists:reverse(Acc),Tokens};
+parse_AlternativeTypeList(Tokens,[]) ->
+ {AlternativeType,Rest} = parse_NamedType(Tokens),
+ parse_AlternativeTypeList(Rest,[AlternativeType]);
+parse_AlternativeTypeList(Tokens,_) ->
+ throw({asn1_error,
+ {get_line(hd(Tokens)),get(asn1_module),
+ [got,[get_token(hd(Tokens)),get_token(hd(tl(Tokens)))],
+ expected,['}',', identifier']]}}).
+
+parse_ExtensionAdditionAlternatives(Tokens =[{',',_}|_],Clist) ->
+ {ExtAddList,Rest2} = parse_ExtensionAdditionAlternativesList(Tokens,[]),
+ {Clist++lists:flatten(ExtAddList),Rest2};
+parse_ExtensionAdditionAlternatives(Tokens,Clist) ->
+ %% Empty
+ {Clist,Tokens}.
+
+parse_ExtensionAdditionAlternativesList([{',',_},Id = {identifier,_,_}|Rest],Acc) ->
+ {AlternativeType,Rest2} = parse_NamedType([Id|Rest]),
+ parse_ExtensionAdditionAlternativesList(Rest2,[AlternativeType|Acc]);
+parse_ExtensionAdditionAlternativesList([{',',_},C1 = {'[',_},C2 = {'[',_}|Rest],Acc) ->
+ {ExtAddGroup,Rest2} = parse_ExtensionAdditionAlternativesGroup([C1,C2|Rest],[]),
+ parse_ExtensionAdditionAlternativesList(Rest2,[ExtAddGroup|Acc]);
+parse_ExtensionAdditionAlternativesList(Tokens = [{'}',_}|_],Acc) ->
+ {lists:reverse(Acc),Tokens};
+parse_ExtensionAdditionAlternativesList(Tokens = [{',',_},{'...',_}|_],Acc) ->
+ {lists:reverse(Acc),Tokens};
+parse_ExtensionAdditionAlternativesList(Tokens,_) ->
+ throw({asn1_error,
+ {get_line(hd(Tokens)),get(asn1_module),
+ [got,[get_token(hd(Tokens)),get_token(hd(tl(Tokens)))],
+ expected,['}',', identifier']]}}).
+
+
+parse_ExtensionAdditionAlternativesGroup([ {'[',_},{'[',_},_VsnNr = {number,_,Num},{':',_}|Rest],[]) ->
+ parse_ExtensionAdditionAlternativesGroup2(Rest,Num);
+parse_ExtensionAdditionAlternativesGroup([ {'[',_},{'[',_}|Rest],[]) ->
+ parse_ExtensionAdditionAlternativesGroup2(Rest,undefined);
+parse_ExtensionAdditionAlternativesGroup(Tokens,_) ->
+ throw({asn1_error,
+ {get_line(hd(Tokens)),get(asn1_module),
+ [got,[get_token(hd(Tokens)),get_token(hd(tl(Tokens)))],
+ expected,['[[']]}}).
+
+
+parse_ExtensionAdditionAlternativesGroup2(Tokens,Num) ->
+ {CompTypeList,Rest} = parse_AlternativeTypeList(Tokens,[]),
case Rest of
- [{',',_},Id = {identifier,_,_}|Rest2] ->
- parse_AlternativeTypeList([Id|Rest2],[NamedType|Acc]);
+ [{']',_},{']',_}|Rest2] ->
+ {[{'ExtensionAdditionGroup',Num}|CompTypeList] ++
+ ['ExtensionAdditionGroupEnd'],Rest2};
_ ->
- {lists:reverse([NamedType|Acc]),Rest}
- end.
-
+ throw({asn1_error,{get_line(hd(Rest)),get(asn1_module),
+ [got,get_token(hd(Rest)),expected,[']]']]}})
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% parse_AlternativeTypeLists(Tokens,ExtensionDefault) ->
+%% {AltTypeList,Rest1} = parse_AlternativeTypeList(Tokens),
+%% {ExtensionAndException,Rest2} =
+%% case Rest1 of
+%% [{',',_},{'...',L1},{'!',_}|Rest12] ->
+%% {_,Rest13} = parse_ExceptionIdentification(Rest12),
+%% %% Exception info is currently thrown away
+%% {[#'EXTENSIONMARK'{pos=L1}],Rest13};
+%% [{',',_},{'...',L1}|Rest12] ->
+%% {[#'EXTENSIONMARK'{pos=L1}],Rest12};
+%% _ ->
+%% {[],Rest1}
+%% end,
+%% {AltTypeList2,Rest5} =
+%% case ExtensionAndException of
+%% [] ->
+%% {AltTypeList,Rest2};
+%% _ ->
+%% {ExtensionAddition,Rest3} =
+%% case Rest2 of
+%% [{',',_}|Rest23] ->
+%% parse_ExtensionAdditionAlternativeList(Rest23);
+%% _ ->
+%% {[],Rest2}
+%% end,
+%% {OptionalExtensionMarker,Rest4} =
+%% case Rest3 of
+%% [{',',_},{'...',L3}|Rest31] ->
+%% {[#'EXTENSIONMARK'{pos=L3}],Rest31};
+%% _ ->
+%% {[],Rest3}
+%% end,
+%% {AltTypeList ++ ExtensionAndException ++
+%% ExtensionAddition ++ OptionalExtensionMarker, Rest4}
+%% end,
+%% AltTypeList3 =
+%% case [X || X=#'EXTENSIONMARK'{} <- AltTypeList2] of
+%% [] when ExtensionDefault == 'IMPLIED' ->
+%% AltTypeList2 ++ [#'EXTENSIONMARK'{}];
+%% _ ->
+%% AltTypeList2
+%% end,
+%% {AltTypeList3,Rest5}.
-parse_ExtensionAdditionAlternativeList(Tokens) ->
- parse_ExtensionAdditionAlternativeList(Tokens,[]).
+%% parse_AlternativeTypeList(Tokens) ->
+%% parse_AlternativeTypeList(Tokens,[]).
+
+%% parse_AlternativeTypeList(Tokens,Acc) ->
+%% {NamedType,Rest} = parse_NamedType(Tokens),
+%% case Rest of
+%% [{',',_},Id = {identifier,_,_}|Rest2] ->
+%% parse_AlternativeTypeList([Id|Rest2],[NamedType|Acc]);
+%% _ ->
+%% {lists:reverse([NamedType|Acc]),Rest}
+%% end.
+
-parse_ExtensionAdditionAlternativeList(Tokens,Acc) ->
- {Element,Rest0} =
- case Tokens of
- [{identifier,_,_}|_Rest] ->
- parse_NamedType(Tokens);
- [{'[',_},{'[',_}|_] ->
- parse_ExtensionAdditionAlternatives(Tokens)
- end,
- case Rest0 of
- [{',',_}|Rest01] ->
- parse_ExtensionAdditionAlternativeList(Rest01,[Element|Acc]);
- _ ->
- {lists:reverse([Element|Acc]),Rest0}
- end.
-parse_ExtensionAdditionAlternatives([{'[',_},{'[',_}|Rest]) ->
- parse_ExtensionAdditionAlternatives(Rest,[]);
-parse_ExtensionAdditionAlternatives(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,'[[']}}).
+%% parse_ExtensionAdditionAlternativeList(Tokens) ->
+%% parse_ExtensionAdditionAlternativeList(Tokens,[]).
+
+%% parse_ExtensionAdditionAlternativeList([{'[[',_}|Rest],Acc) ->
+%% parse_ExtensionAdditionAlternativeList(Rest,Acc);
+%% parse_ExtensionAdditionAlternativeList(Tokens = [{identifier,_,_}|_Rest],Acc) ->
+%% {Element,Rest0} = parse_NamedType(Tokens);
+%% case Rest0 of
+%% [{',',_}|Rest01] ->
+%% parse_ExtensionAdditionAlternativeList(Rest01,[Element|Acc]);
+%% _ ->
+%% {lists:reverse([Element|Acc]),Rest0}
+%% end.
-parse_ExtensionAdditionAlternatives([Id = {identifier,_,_}|Rest],Acc) ->
- {NamedType, Rest2} = parse_NamedType([Id|Rest]),
- case Rest2 of
- [{',',_}|Rest21] ->
- parse_ExtensionAdditionAlternatives(Rest21,[NamedType|Acc]);
- [{']',_},{']',_}|Rest21] ->
- {lists:reverse(Acc),Rest21};
- _ ->
- throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
- [got,get_token(hd(Rest2)),expected,[',',']]']]}})
- end.
+%% parse_ExtensionAdditionAlternatives([{'[[',_}|Rest]) ->
+%% parse_ExtensionAdditionAlternatives(Rest,[]);
+%% parse_ExtensionAdditionAlternatives(Tokens) ->
+%% throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+%% [got,get_token(hd(Tokens)),expected,'[[']}}).
+
+%% parse_ExtensionAdditionAlternatives([Id = {identifier,_,_}|Rest],Acc) ->
+%% {NamedType, Rest2} = parse_NamedType([Id|Rest]),
+%% case Rest2 of
+%% [{',',_}|Rest21] ->
+%% parse_ExtensionAdditionAlternatives(Rest21,[NamedType|Acc]);
+%% [{']]',_}|Rest21] ->
+%% {lists:reverse(Acc),Rest21};
+%% _ ->
+%% throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
+%% [got,get_token(hd(Rest2)),expected,[',',']]']]}})
+%% end.
parse_NamedType([{identifier,L1,Idname}|Rest]) ->
{Type,Rest2} = parse_Type(Rest),
@@ -2428,144 +2540,123 @@ parse_NamedType(Tokens) ->
parse_ComponentTypeLists(Tokens) ->
-% Resulting tuple {ComponentTypeList,Rest1} is returned
- case Tokens of
- [{identifier,_,_}|_Rest0] ->
- {Clist,Rest01} = parse_ComponentTypeList(Tokens),
- case Rest01 of
- [{',',_}|Rest02] ->
- parse_ComponentTypeLists(Rest02,Clist); % 5 - 13
- _ ->
- {Clist,Rest01}
- end;
- [{'COMPONENTS',_},{'OF',_}|_Rest] ->
- {Clist,Rest01} = parse_ComponentTypeList(Tokens),
- case Rest01 of
- [{',',_}|Rest02] ->
- parse_ComponentTypeLists(Rest02,Clist);
- _ ->
- {Clist,Rest01}
- end;
+ parse_ComponentTypeLists(Tokens,[]).
+
+parse_ComponentTypeLists(Tokens = [{identifier,_,_}|_Rest0],Clist) ->
+ {CompList,Rest1} = parse_ComponentTypeList(Tokens,[]),
+ parse_ComponentTypeLists(Rest1,Clist++CompList);
+parse_ComponentTypeLists(Tokens = [{'COMPONENTS',_},{'OF',_}|_Rest],Clist) ->
+ {CompList,Rest1} = parse_ComponentTypeList(Tokens,[]),
+ parse_ComponentTypeLists(Rest1,Clist++CompList);
+parse_ComponentTypeLists([{'...',L1},{'!',_}|Rest02],Clist0) ->
+ {_,Rest03} = parse_ExceptionIdentification(Rest02),
+ %% Exception info is currently thrown away
+ parse_ComponentTypeLists2(Rest03,Clist0++[#'EXTENSIONMARK'{pos=L1}]);
+parse_ComponentTypeLists([{',',L1},{'...',_},{'!',_}|Rest02],Clist0) when Clist0 =/= []->
+ {_,Rest03} = parse_ExceptionIdentification(Rest02),
+ %% Exception info is currently thrown away
+ parse_ComponentTypeLists2(Rest03,Clist0++[#'EXTENSIONMARK'{pos=L1}]);
+
+ parse_ComponentTypeLists([{',',_},{'...',L1}|Rest02],Clist0) when Clist0 =/= []->
+ parse_ComponentTypeLists2(Rest02,Clist0++[#'EXTENSIONMARK'{pos=L1}]);
+parse_ComponentTypeLists([{'...',L1}|Rest02],Clist0) ->
+ parse_ComponentTypeLists2(Rest02,Clist0++[#'EXTENSIONMARK'{pos=L1}]);
+parse_ComponentTypeLists(Tokens = [{'}',_L1}|_Rest02],Clist0) ->
+ {Clist0,Tokens}.
+
+parse_ComponentTypeLists2(Tokens,Clist) ->
+ {ExtAdd,Rest} = parse_ExtensionAdditions(Tokens,Clist),
+ {Clist2,Rest2} = parse_OptionalExtensionMarker(Rest,lists:flatten(ExtAdd)),
+ case Rest2 of
+ [{',',_}|Rest3] ->
+ {CompList,Rest4} = parse_ComponentTypeList(Rest3,[]),
+ {Clist2 ++ CompList,Rest4};
_ ->
- parse_ComponentTypeLists(Tokens,[])
+ {Clist2,Rest2}
end.
-parse_ComponentTypeLists([{'...',L1},{'!',_}|Rest],Clist1) ->
- {_,Rest2} = parse_ExceptionIdentification(Rest),
- %% Exception info is currently thrown away
- parse_ComponentTypeLists2(Rest2,Clist1++[#'EXTENSIONMARK'{pos=L1}]);
-parse_ComponentTypeLists([{'...',L1}|Rest],Clist1) -> %% first Extensionmark
- parse_ComponentTypeLists2(Rest,Clist1++[#'EXTENSIONMARK'{pos=L1}]);
-parse_ComponentTypeLists(Tokens,Clist1) ->
- {Clist1,Tokens}.
-
-
-parse_ComponentTypeLists2(Tokens,Clist1) ->
- {ExtensionAddition,Rest2} =
- case Tokens of
- [{',',_}|Rest1] ->
- parse_ExtensionAdditionList(Rest1);
- _ ->
- {[],Tokens}
- end,
- {OptionalExtensionMarker,Rest3} =
- case Rest2 of
- [{',',_},{'...',L2}|Rest21] ->
- {[#'EXTENSIONMARK'{pos=L2}],Rest21};
- _ ->
- {[],Rest2}
- end,
- {RootComponentTypeList,Rest4} =
- case Rest3 of
- [{',',_}|Rest31] ->
- parse_ComponentTypeList(Rest31);
- _ ->
- {[],Rest3}
- end,
- {Clist1 ++ ExtensionAddition ++ OptionalExtensionMarker ++ RootComponentTypeList, Rest4}.
-
+parse_OptionalExtensionMarker([{',',_},{'...',L1}|Rest],Clist)->
+ {Clist++[#'EXTENSIONMARK'{pos=L1}],Rest};
+parse_OptionalExtensionMarker(Tokens,Clist) ->
+ {Clist,Tokens}.
-parse_ComponentTypeList(Tokens) ->
- parse_ComponentTypeList(Tokens,[]).
-parse_ComponentTypeList(Tokens,Acc) ->
+parse_ComponentTypeList([{',',_},Id = {identifier,_,_}|Rest],Acc) when Acc =/= [] ->
+ {ComponentType,Rest2} = parse_ComponentType([Id|Rest]),
+ parse_ComponentTypeList(Rest2,[ComponentType|Acc]);
+parse_ComponentTypeList([{',',_},C1={'COMPONENTS',_},C2={'OF',_}|Rest],Acc) when Acc =/= [] ->
+ {ComponentType,Rest2} = parse_ComponentType([C1,C2|Rest]),
+ parse_ComponentTypeList(Rest2,[ComponentType|Acc]);
+parse_ComponentTypeList(Tokens = [{'}',_}|_],Acc) ->
+ {lists:reverse(Acc),Tokens};
+parse_ComponentTypeList(Tokens = [{']',_},{']',_}|_],Acc) ->
+ {lists:reverse(Acc),Tokens};
+parse_ComponentTypeList(Tokens = [{',',_},{'...',_}|_],Acc) ->
+ {lists:reverse(Acc),Tokens};
+parse_ComponentTypeList(Tokens,[]) ->
{ComponentType,Rest} = parse_ComponentType(Tokens),
+ parse_ComponentTypeList(Rest,[ComponentType]);
+parse_ComponentTypeList(Tokens,_) ->
+ throw({asn1_error,
+ {get_line(hd(Tokens)),get(asn1_module),
+ [got,[get_token(hd(Tokens)),get_token(hd(tl(Tokens)))],
+ expected,['}',', identifier']]}}).
+
+parse_ExtensionAdditions(Tokens=[{',',_}|_],Clist) ->
+ {ExtAddList,Rest2} = parse_ExtensionAdditionList(Tokens,[]),
+ {Clist++ExtAddList,Rest2};
+parse_ExtensionAdditions(Tokens,Clist) ->
+ %% Empty
+ {Clist,Tokens}.
+
+parse_ExtensionAdditionList([{',',_},Id = {identifier,_,_}|Rest],Acc) ->
+ {ComponentType,Rest2} = parse_ComponentType([Id|Rest]),
+ parse_ExtensionAdditionList(Rest2,[ComponentType|Acc]);
+parse_ExtensionAdditionList([{',',_},C1={'COMPONENTS',_},C2={'OF',_}|Rest],Acc) ->
+ {ComponentType,Rest2} = parse_ComponentType([C1,C2|Rest]),
+ parse_ExtensionAdditionList(Rest2,[ComponentType|Acc]);
+parse_ExtensionAdditionList([{',',_},C1 = {'[',_},C2 = {'[',_}|Rest],Acc) ->
+ {ExtAddGroup,Rest2} = parse_ExtensionAdditionGroup([C1,C2|Rest],[]),
+ parse_ExtensionAdditionList(Rest2,[ExtAddGroup|Acc]);
+parse_ExtensionAdditionList(Tokens = [{'}',_}|_],Acc) ->
+ {lists:reverse(Acc),Tokens};
+parse_ExtensionAdditionList(Tokens = [{',',_},{'...',_}|_],Acc) ->
+ {lists:reverse(Acc),Tokens};
+parse_ExtensionAdditionList(Tokens,_) ->
+ throw({asn1_error,
+ {get_line(hd(Tokens)),get(asn1_module),
+ [got,[get_token(hd(Tokens)),get_token(hd(tl(Tokens)))],
+ expected,['}',', identifier']]}}).
+
+
+parse_ExtensionAdditionGroup([ {'[',_},{'[',_},_VsnNr = {number,_,Num},{':',_}|Rest],[]) ->
+ parse_ExtensionAdditionGroup2(Rest,Num);
+parse_ExtensionAdditionGroup([ {'[',_},{'[',_}|Rest],[]) ->
+ parse_ExtensionAdditionGroup2(Rest,undefined);
+parse_ExtensionAdditionGroup(Tokens,_) ->
+ throw({asn1_error,
+ {get_line(hd(Tokens)),get(asn1_module),
+ [got,[get_token(hd(Tokens)),get_token(hd(tl(Tokens)))],
+ expected,['[[']]}}).
+
+
+parse_ExtensionAdditionGroup2(Tokens,Num) ->
+ {CompTypeList,Rest} = parse_ComponentTypeList(Tokens,[]),
case Rest of
- [{',',_},Id = {identifier,_,_}|Rest2] ->
- parse_ComponentTypeList([Id|Rest2],[ComponentType|Acc]);
- [{',',_},C1={'COMPONENTS',_},C2={'OF',_}|Rest2] ->
- parse_ComponentTypeList([C1,C2|Rest2],[ComponentType|Acc]);
-% _ ->
-% {lists:reverse([ComponentType|Acc]),Rest}
- [{'}',_}|_] ->
- {lists:reverse([ComponentType|Acc]),Rest};
-% [{',',_},{'...',_},{'}',_}|_] ->
-% {lists:reverse([ComponentType|Acc]),Rest};
- [{',',_},{'...',_}|_] ->%% here comes the dubble ellipse
- {lists:reverse([ComponentType|Acc]),Rest};
+ [{']',_},{']',_}|Rest2] ->
+ {[{'ExtensionAdditionGroup',Num}|CompTypeList] ++
+ ['ExtensionAdditionGroupEnd'],Rest2};
_ ->
- throw({asn1_error,
- {get_line(hd(Tokens)),get(asn1_module),
- [got,[get_token(hd(Rest)),get_token(hd(tl(Rest)))],
- expected,['}',', identifier']]}})
- end.
-
-
-parse_ExtensionAdditionList(Tokens) ->
- parse_ExtensionAdditionList(Tokens,[]).
-
-parse_ExtensionAdditionList(Tokens,Acc) ->
- {Element,Rest0} =
- case Tokens of
- [{identifier,_,_}|_Rest] ->
- parse_ComponentType(Tokens);
- [{'[',_},{'[',_}|_] ->
- parse_ExtensionAdditions(Tokens);
- [{'...',L1}|_Rest] ->
- {#'EXTENSIONMARK'{pos=L1},Tokens};
- _ ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,
- [identifier,'[[']]}})
- end,
- case Rest0 of
- [{',',_}|Rest01] ->
- parse_ExtensionAdditionList(Rest01,[Element|Acc]);
- [{'...',_}|Rest01] ->
- {lists:reverse([Element|Acc]),Rest01};
- _ ->
- {lists:reverse([Element|Acc]),Rest0}
+ throw({asn1_error,{get_line(hd(Rest)),get(asn1_module),
+ [got,get_token(hd(Rest)),expected,[']]']]}})
end.
-parse_ExtensionAdditions([{'[',_},{'[',_}|Rest]) ->
- parse_ExtensionAdditions(Rest,[]);
-parse_ExtensionAdditions(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,'[[']}}).
-
-parse_ExtensionAdditions([_VsnNr = {number,_,_},{':',_}|Rest],Acc) ->
- %% ignor version number for now
- parse_ExtensionAdditions(Rest,Acc);
-parse_ExtensionAdditions([Id = {identifier,_,_}|Rest],Acc) ->
- {ComponentType, Rest2} = parse_ComponentType([Id|Rest]),
- case Rest2 of
- [{',',_}|Rest21] ->
- parse_ExtensionAdditions(Rest21,[ComponentType|Acc]);
- [{']',_},{']',_}|Rest21] ->
- {lists:reverse(Acc),Rest21};
- _ ->
- throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
- [got,get_token(hd(Rest2)),expected,[',',']]']]}})
- end;
-parse_ExtensionAdditions(Tokens,_) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,identifier]}}).
parse_ComponentType([{'COMPONENTS',_},{'OF',_}|Rest]) ->
{Type,Rest2} = parse_Type(Rest),
{{'COMPONENTS OF',Type},Rest2};
parse_ComponentType(Tokens) ->
- {NamedType,Rest} = parse_NamedType(Tokens),
+ Result = {NamedType,Rest} = parse_NamedType(Tokens),
case Rest of
[{'OPTIONAL',_}|Rest2] ->
{NamedType#'ComponentType'{prop='OPTIONAL'},Rest2};
@@ -2573,7 +2664,7 @@ parse_ComponentType(Tokens) ->
{Value,Rest21} = parse_Value(Rest2),
{NamedType#'ComponentType'{prop={'DEFAULT',Value}},Rest21};
_ ->
- {NamedType,Rest}
+ Result
end.
diff --git a/lib/asn1/src/asn1ct_tok.erl b/lib/asn1/src/asn1ct_tok.erl
index f0ce31bdb2..85199c65ec 100644
--- a/lib/asn1/src/asn1ct_tok.erl
+++ b/lib/asn1/src/asn1ct_tok.erl
@@ -21,7 +21,7 @@
%% Tokenize ASN.1 code (input to parser generated with yecc)
--export([get_name/2,tokenise/2, file/1]).
+-export([get_name/2,tokenise/4, file/1]).
file(File) ->
@@ -29,12 +29,9 @@ file(File) ->
{error, Reason} ->
{error,{File,file:format_error(Reason)}};
{ok,Stream} ->
- process0(Stream)
+ process(Stream,0,[])
end.
-process0(Stream) ->
- process(Stream,0,[]).
-
process(Stream,Lno,R) ->
process(io:get_line(Stream, ''), Stream,Lno+1,R).
@@ -45,131 +42,128 @@ process(eof, Stream,Lno,R) ->
process(L, Stream,Lno,R) when is_list(L) ->
%%io:format('read:~s',[L]),
- case catch tokenise(L,Lno) of
+ case catch tokenise(Stream,L,Lno,[]) of
{'ERR',Reason} ->
io:format("Tokeniser error on line: ~w ~w~n",[Lno,Reason]),
exit(0);
- {multiline_comment,NestingLevel} ->
- {RestL,Lno2} = process_skip_multiline_comment(Stream,Lno,NestingLevel),
- process(RestL,Stream,Lno2,R);
- T ->
+ {NewLno,T} ->
%%io:format('toks:~w~n',[T]),
- process(Stream,Lno,[T|R])
+ process(Stream,NewLno,[T|R])
end.
-process_skip_multiline_comment(Stream,Lno,NestingLevel) ->
- process_skip_multiline_comment(io:get_line(Stream, ''),
- Stream, Lno + 1, NestingLevel).
-process_skip_multiline_comment(eof,_Stream,Lno,_NestingLevel) ->
- io:format("Tokeniser error on line: ~w, premature end of multiline comment~n",[Lno]),
- exit(0);
-process_skip_multiline_comment(Line,Stream,Lno,NestingLevel) ->
- case catch skip_multiline_comment(Line,NestingLevel) of
- {multiline_comment,NestingLevel2} ->
- process_skip_multiline_comment(Stream,Lno,NestingLevel2);
- T ->
- {T,Lno}
- end.
-
-tokenise([H|T],Lno) when $a =< H , H =< $z ->
+tokenise(Stream,[H|T],Lno,R) when $a =< H , H =< $z ->
{X, T1} = get_name(T, [H]),
- [{identifier,Lno, list_to_atom(X)}|tokenise(T1,Lno)];
+ tokenise(Stream,T1,Lno,[{identifier,Lno, list_to_atom(X)}|R]);
-tokenise([$&,H|T],Lno) when $A =< H , H =< $Z ->
+tokenise(Stream,[$&,H|T],Lno,R) when $A =< H , H =< $Z ->
{Y, T1} = get_name(T, [H]),
X = list_to_atom(Y),
- [{typefieldreference, Lno, X} | tokenise(T1, Lno)];
+ tokenise(Stream,T1,Lno,[{typefieldreference, Lno, X} | R]);
-tokenise([$&,H|T],Lno) when $a =< H , H =< $z ->
+tokenise(Stream,[$&,H|T],Lno,R) when $a =< H , H =< $z ->
{Y, T1} = get_name(T, [H]),
X = list_to_atom(Y),
- [{valuefieldreference, Lno, X} | tokenise(T1, Lno)];
+ tokenise(Stream,T1,Lno,[{valuefieldreference, Lno, X} | R]);
-tokenise([H|T],Lno) when $A =< H , H =< $Z ->
+tokenise(Stream,[H|T],Lno,R) when $A =< H , H =< $Z ->
{Y, T1} = get_name(T, [H]),
X = list_to_atom(Y),
case reserved_word(X) of
true ->
- [{X,Lno}|tokenise(T1,Lno)];
+ tokenise(Stream,T1,Lno,[{X,Lno}|R]);
false ->
- [{typereference,Lno,X}|tokenise(T1,Lno)];
+ tokenise(Stream,T1,Lno,[{typereference,Lno,X}|R]);
rstrtype ->
- [{restrictedcharacterstringtype,Lno,X}|tokenise(T1,Lno)]
+ tokenise(Stream,T1,Lno,[{restrictedcharacterstringtype,Lno,X}|R])
end;
-tokenise([$-,H|T],Lno) when $0 =< H , H =< $9 ->
+tokenise(Stream,[$-,H|T],Lno,R) when $0 =< H , H =< $9 ->
{X, T1} = get_number(T, [H]),
- [{number,Lno,-1 * list_to_integer(X)}|tokenise(T1,Lno)];
+ tokenise(Stream,T1,Lno,[{number,Lno,-1 * list_to_integer(X)}|R]);
-tokenise([H|T],Lno) when $0 =< H , H =< $9 ->
+tokenise(Stream,[H|T],Lno,R) when $0 =< H , H =< $9 ->
{X, T1} = get_number(T, [H]),
- [{number,Lno,list_to_integer(X)}|tokenise(T1,Lno)];
+ tokenise(Stream,T1,Lno,[{number,Lno,list_to_integer(X)}|R]);
-tokenise([$-,$-|T],Lno) ->
- tokenise(skip_comment(T),Lno);
+tokenise(Stream,[$-,$-|T],Lno,R) ->
+ tokenise(Stream,skip_comment(T),Lno,R);
-tokenise([$/,$*|T],Lno) ->
- tokenise(skip_multiline_comment(T,0),Lno);
+tokenise(Stream,[$/,$*|T],Lno,R) ->
+ {NewLno,T1} = skip_multiline_comment(Stream,T,Lno,0),
+ tokenise(Stream,T1,NewLno,R);
-tokenise([$:,$:,$=|T],Lno) ->
- [{'::=',Lno}|tokenise(T,Lno)];
+tokenise(Stream,[$:,$:,$=|T],Lno,R) ->
+ tokenise(Stream,T,Lno,[{'::=',Lno}|R]);
-tokenise([$'|T],Lno) ->
+tokenise(Stream,[$'|T],Lno,R) ->
case catch collect_quoted(T,Lno,[]) of
{'ERR',_} ->
throw({'ERR','bad_quote'});
{Thing, T1} ->
- [Thing|tokenise(T1,Lno)]
+ tokenise(Stream,T1,Lno,[Thing|R])
end;
-tokenise([$"|T],Lno) ->
- collect_string(T,Lno);
+tokenise(Stream,[$"|T],Lno,R) ->
+ {Str,T1} = collect_string(T,Lno),
+ tokenise(Stream,T1,Lno,[Str|R]);
+
+tokenise(Stream,[${|T],Lno,R) ->
+ tokenise(Stream,T,Lno,[{'{',Lno}|R]);
+
+tokenise(Stream,[$}|T],Lno,R) ->
+ tokenise(Stream,T,Lno,[{'}',Lno}|R]);
-tokenise([${|T],Lno) ->
- [{'{',Lno}|tokenise(T,Lno)];
+%% tokenise(Stream,[$],$]|T],Lno,R) ->
+%% tokenise(Stream,T,Lno,[{']]',Lno}|R]);
-tokenise([$}|T],Lno) ->
- [{'}',Lno}|tokenise(T,Lno)];
+%% Even though x.680 specify '[[' and ']]' as lexical items
+%% it does not work to have them as such since the single [ and ] can
+%% be used beside each other in the SYNTAX OF in x.681
+%% the solution chosen here , i.e. to have them as separate lexical items
+%% will not detect the cases where there is white space between them
+%% which would be an error in the use in ExtensionAdditionGroups
-tokenise([$]|T],Lno) ->
- [{']',Lno}|tokenise(T,Lno)];
+%% tokenise(Stream,[$[,$[|T],Lno,R) ->
+%% tokenise(Stream,T,Lno,[{'[[',Lno}|R]);
-tokenise([$[|T],Lno) ->
- [{'[',Lno}|tokenise(T,Lno)];
+tokenise(Stream,[$]|T],Lno,R) ->
+ tokenise(Stream,T,Lno,[{']',Lno}|R]);
-tokenise([$,|T],Lno) ->
- [{',',Lno}|tokenise(T,Lno)];
+tokenise(Stream,[$[|T],Lno,R) ->
+ tokenise(Stream,T,Lno,[{'[',Lno}|R]);
-tokenise([$(|T],Lno) ->
- [{'(',Lno}|tokenise(T,Lno)];
-tokenise([$)|T],Lno) ->
- [{')',Lno}|tokenise(T,Lno)];
+tokenise(Stream,[$,|T],Lno,R) ->
+ tokenise(Stream,T,Lno,[{',',Lno}|R]);
-tokenise([$.,$.,$.|T],Lno) ->
- [{'...',Lno}|tokenise(T,Lno)];
+tokenise(Stream,[$(|T],Lno,R) ->
+ tokenise(Stream,T,Lno,[{'(',Lno}|R]);
+tokenise(Stream,[$)|T],Lno,R) ->
+ tokenise(Stream,T,Lno,[{')',Lno}|R]);
-tokenise([$.,$.|T],Lno) ->
- [{'..',Lno}|tokenise(T,Lno)];
+tokenise(Stream,[$.,$.,$.|T],Lno,R) ->
+ tokenise(Stream,T,Lno,[{'...',Lno}|R]);
-tokenise([$.|T],Lno) ->
- [{'.',Lno}|tokenise(T,Lno)];
-tokenise([$^|T],Lno) ->
- [{'^',Lno}|tokenise(T,Lno)];
-tokenise([$!|T],Lno) ->
- [{'!',Lno}|tokenise(T,Lno)];
-tokenise([$||T],Lno) ->
- [{'|',Lno}|tokenise(T,Lno)];
+tokenise(Stream,[$.,$.|T],Lno,R) ->
+ tokenise(Stream,T,Lno,[{'..',Lno}|R]);
+tokenise(Stream,[$.|T],Lno,R) ->
+ tokenise(Stream,T,Lno,[{'.',Lno}|R]);
+tokenise(Stream,[$^|T],Lno,R) ->
+ tokenise(Stream,T,Lno,[{'^',Lno}|R]);
+tokenise(Stream,[$!|T],Lno,R) ->
+ tokenise(Stream,T,Lno,[{'!',Lno}|R]);
+tokenise(Stream,[$||T],Lno,R) ->
+ tokenise(Stream,T,Lno,[{'|',Lno}|R]);
-tokenise([H|T],Lno) ->
+tokenise(Stream,[H|T],Lno,R) ->
case white_space(H) of
true ->
- tokenise(T,Lno);
+ tokenise(Stream,T,Lno,R);
false ->
- [{list_to_atom([H]),Lno}|tokenise(T,Lno)]
+ tokenise(Stream,T,Lno,[{list_to_atom([H]),Lno}|R])
end;
-tokenise([],_) ->
- [].
+tokenise(_Stream,[],Lno,R) ->
+ {Lno,lists:reverse(R)}.
collect_string(L,Lno) ->
@@ -181,7 +175,7 @@ collect_string([],_,_) ->
collect_string([H|T],Lno,Str) ->
case H of
$" ->
- [{cstring,1,lists:reverse(Str)}|tokenise(T,Lno)];
+ {{cstring,1,lists:reverse(Str)},T};
Ch ->
collect_string(T,Lno,[Ch|Str])
end.
@@ -252,17 +246,23 @@ skip_comment([_|T]) ->
skip_comment(T).
-skip_multiline_comment([],L) ->
- throw({multiline_comment,L});
-skip_multiline_comment([$*,$/|T],0) ->
- T;
-skip_multiline_comment([$*,$/|T],Level) ->
- skip_multiline_comment(T,Level - 1);
-skip_multiline_comment([$/,$*|T],Level) ->
- skip_multiline_comment(T,Level + 1);
-skip_multiline_comment([_|T],Level) ->
- skip_multiline_comment(T,Level).
-
+skip_multiline_comment(Stream,[],Lno,Level) ->
+ case io:get_line(Stream,'') of
+ eof ->
+ io:format("Tokeniser error on line: ~w~n"
+ "premature end of multiline comment~n",[Lno]),
+ exit(0);
+ Line ->
+ skip_multiline_comment(Stream,Line,Lno+1,Level)
+ end;
+skip_multiline_comment(_Stream,[$*,$/|T],Lno,0) ->
+ {Lno,T};
+skip_multiline_comment(Stream,[$*,$/|T],Lno,Level) ->
+ skip_multiline_comment(Stream,T,Lno,Level - 1);
+skip_multiline_comment(Stream,[$/,$*|T],Lno,Level) ->
+ skip_multiline_comment(Stream,T,Lno,Level + 1);
+skip_multiline_comment(Stream,[_|T],Lno,Level) ->
+ skip_multiline_comment(Stream,T,Lno,Level).
collect_quoted([$',$B|T],Lno, L) ->
case check_bin(L) of
diff --git a/lib/asn1/src/asn1rt_uper_bin.erl b/lib/asn1/src/asn1rt_uper_bin.erl
index a964b835ae..abe178a69e 100644
--- a/lib/asn1/src/asn1rt_uper_bin.erl
+++ b/lib/asn1/src/asn1rt_uper_bin.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1611,25 +1611,8 @@ complete_NFP(InList) when is_bitstring(InList) ->
%% 10.5.6 NOTE: If "range" satisfies the inequality 2^m < "range" =<
%% 2^(m+1) then the number of bits = m + 1
-num_bits(1) -> 0;
-num_bits(2) -> 1;
-num_bits(R) when R =< 4 ->
- 2;
-num_bits(R) when R =< 8 ->
- 3;
-num_bits(R) when R =< 16 ->
- 4;
-num_bits(R) when R =< 32 ->
- 5;
-num_bits(R) when R =< 64 ->
- 6;
-num_bits(R) when R =< 128 ->
- 7;
-num_bits(R) when R =< 256 ->
- 8;
-num_bits(R) when R =< 512 ->
- 9;
-num_bits(R) when R =< 1024 ->
- 10;
-num_bits(R) ->
- 1+num_bits(R bsr 1).
+
+num_bits(N) ->
+ num_bits(N,1,0).
+num_bits(N,T,B) when N=<T->B;
+num_bits(N,T,B) ->num_bits(N,T bsl 1, B+1).
diff --git a/lib/asn1/test/Makefile b/lib/asn1/test/Makefile
index 5014eb902b..e8f65ec70b 100644
--- a/lib/asn1/test/Makefile
+++ b/lib/asn1/test/Makefile
@@ -189,27 +189,16 @@ release_spec: opt
release_tests_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)
- $(INSTALL_DATA) asn1.spec $(EMAKEFILE) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)
- chmod -f -R u+w $(RELSYSDIR)
- @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+ $(INSTALL_DIR) $(RELSYSDIR)/asn1_SUITE_data
$(INSTALL_DIR) $(RELSYSDIR)/asn1_bin_SUITE_data
- @(cd asn1_SUITE_data; tar cf - *) | (cd $(RELSYSDIR)/asn1_bin_SUITE_data; tar xf -)
$(INSTALL_DIR) $(RELSYSDIR)/asn1_bin_v2_SUITE_data
- @(cd asn1_SUITE_data; tar cf - *) | (cd $(RELSYSDIR)/asn1_bin_v2_SUITE_data; tar xf -)
-
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)
+ $(INSTALL_DATA) asn1.spec $(INSTALL_PROGS) $(RELSYSDIR)
+ chmod -f -R u+w $(RELSYSDIR)
+ cd asn1_SUITE_data; tar cfh $(RELSYSDIR)/asn1_SUITE_data.tar *
+ cd $(RELSYSDIR)/asn1_SUITE_data; tar xf $(RELSYSDIR)/asn1_SUITE_data.tar
+ cd $(RELSYSDIR)/asn1_bin_SUITE_data; tar xf $(RELSYSDIR)/asn1_SUITE_data.tar
+ cd $(RELSYSDIR)/asn1_bin_v2_SUITE_data; tar xf $(RELSYSDIR)/asn1_SUITE_data.tar
+ rm $(RELSYSDIR)/asn1_SUITE_data.tar
release_docs_spec:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/asn1/test/asn1_SUITE.erl.src b/lib/asn1/test/asn1_SUITE.erl.src
index ca73d259af..e1a09adc82 100644
--- a/lib/asn1/test/asn1_SUITE.erl.src
+++ b/lib/asn1/test/asn1_SUITE.erl.src
@@ -74,6 +74,7 @@ all(suite) -> [compile,parse,default_per,default_ber,default_per_opt,per,
testSeqTypeRefPrim, testSeqTypeRefSeq, testSeqTypeRefSet,
testSeqOf, testSeqOfIndefinite, testSeqOfCho,
testSeqOfExternal, testSetDefault, testSetExtension,
+ testExtensionAdditionGroup,
testSetExternal, testSeqOfTag, testSetOptional, testSetPrim,
testSetTag, testSetTypeRefCho, testSetTypeRefPrim,
testSetTypeRefSeq, testSetTypeRefSet, testSetOf, testSetOfCho,
@@ -95,7 +96,7 @@ all(suite) -> [compile,parse,default_per,default_ber,default_per_opt,per,
testSSLspecs, testNortel,test_undecoded_rest,
test_inline, testTcapsystem, testNBAPsystem,
test_compile_options,testDoubleEllipses, test_modified_x420,
- testX420, test_x691,ticket_6143
+ testX420, test_x691,ticket_6143, testExtensionAdditionGroup
] ++ common() ++ particular().
%all(suite) -> [test_inline,testNBAPsystem,test_compile_options,ticket_6143].
@@ -1036,7 +1037,6 @@ testSetExtension_cases(Rules) ->
?line testSetExtension:main(Rules).
-
testSetExternal(suite) -> [];
testSetExternal(Config) ->
?line true = code:add_patha(?config(priv_dir,Config)),
@@ -2292,6 +2292,25 @@ ticket_6143(suite) -> [];
ticket_6143(Config) ->
?line ok = test_compile_options:ticket_6143(Config).
+testExtensionAdditionGroup(suite) -> [];
+testExtensionAdditionGroup(Config) ->
+ ?line DataDir = ?config(data_dir,Config),
+ ?line PrivDir = ?config(priv_dir,Config),
+ ?line Path = code:get_path(),
+ ?line code:add_patha(PrivDir),
+ DoIt = fun(Erule) ->
+ ?line ok = asn1ct:compile(filename:join(DataDir,"Extension-Addition-Group"),Erule ++ [{outdir,PrivDir}]),
+ ?line {ok,_M} = compile:file(filename:join(DataDir,"extensionAdditionGroup"),[{i,PrivDir},{outdir,PrivDir},debug_info]),
+ ?line ok = extensionAdditionGroup:run(Erule),
+ ?line ok = extensionAdditionGroup:run2(Erule),
+ ?line ok = asn1ct:compile(filename:join(DataDir,"EUTRA-RRC-Definitions"),Erule ++ [{record_name_prefix,"RRC-"},{outdir,PrivDir}]),
+ ?line ok = extensionAdditionGroup:run3(Erule)
+ end,
+ ?line [DoIt(Rule)|| Rule <- [[per_bin],[per_bin,optimize],[uper_bin]]],
+ %% FIXME problems with automatic tags [ber_bin],[ber_bin,optimize]
+ ?line code:set_path(Path).
+
+
% parse_modules() ->
% ["ImportsFrom"].
diff --git a/lib/asn1/test/asn1_SUITE_data/AA2.asn1db b/lib/asn1/test/asn1_SUITE_data/AA2.asn1db
index 3bf2c1b89d..163dbb032d 100644
--- a/lib/asn1/test/asn1_SUITE_data/AA2.asn1db
+++ b/lib/asn1/test/asn1_SUITE_data/AA2.asn1db
Binary files differ
diff --git a/lib/asn1/test/asn1_SUITE_data/EUTRA-RRC-Definitions.asn b/lib/asn1/test/asn1_SUITE_data/EUTRA-RRC-Definitions.asn
index a451874ef0..3b811dafe6 100644
--- a/lib/asn1/test/asn1_SUITE_data/EUTRA-RRC-Definitions.asn
+++ b/lib/asn1/test/asn1_SUITE_data/EUTRA-RRC-Definitions.asn
@@ -1,2640 +1,3155 @@
--- 3GPP TS 36.331 V8.8.0 (2009-12)
--- $Id$
---
-EUTRA-RRC-Definitions DEFINITIONS AUTOMATIC TAGS ::=
-
-BEGIN
-
-
-BCCH-BCH-Message ::= SEQUENCE {
- message BCCH-BCH-MessageType
-}
-
-BCCH-BCH-MessageType ::= MasterInformationBlock
-
-
-BCCH-DL-SCH-Message ::= SEQUENCE {
- message BCCH-DL-SCH-MessageType
-}
-
-BCCH-DL-SCH-MessageType ::= CHOICE {
- c1 CHOICE {
- systemInformation SystemInformation,
- systemInformationBlockType1 SystemInformationBlockType1
- },
- messageClassExtension SEQUENCE {}
-}
-
-
-PCCH-Message ::= SEQUENCE {
- message PCCH-MessageType
-}
-
-PCCH-MessageType ::= CHOICE {
- c1 CHOICE {
- paging Paging
- },
- messageClassExtension SEQUENCE {}
-}
-
-
-DL-CCCH-Message ::= SEQUENCE {
- message DL-CCCH-MessageType
-}
-
-DL-CCCH-MessageType ::= CHOICE {
- c1 CHOICE {
- rrcConnectionReestablishment RRCConnectionReestablishment,
- rrcConnectionReestablishmentReject RRCConnectionReestablishmentReject,
- rrcConnectionReject RRCConnectionReject,
- rrcConnectionSetup RRCConnectionSetup
- },
- messageClassExtension SEQUENCE {}
-}
-
-
-DL-DCCH-Message ::= SEQUENCE {
- message DL-DCCH-MessageType
-}
-
-DL-DCCH-MessageType ::= CHOICE {
- c1 CHOICE {
- csfbParametersResponseCDMA2000 CSFBParametersResponseCDMA2000,
- dlInformationTransfer DLInformationTransfer,
- handoverFromEUTRAPreparationRequest HandoverFromEUTRAPreparationRequest,
- mobilityFromEUTRACommand MobilityFromEUTRACommand,
- rrcConnectionReconfiguration RRCConnectionReconfiguration,
- rrcConnectionRelease RRCConnectionRelease,
- securityModeCommand SecurityModeCommand,
- ueCapabilityEnquiry UECapabilityEnquiry,
- counterCheck CounterCheck,
- spare7 NULL,
- spare6 NULL, spare5 NULL, spare4 NULL,
- spare3 NULL, spare2 NULL, spare1 NULL
- },
- messageClassExtension SEQUENCE {}
-}
-
-
-UL-CCCH-Message ::= SEQUENCE {
- message UL-CCCH-MessageType
-}
-
-UL-CCCH-MessageType ::= CHOICE {
- c1 CHOICE {
- rrcConnectionReestablishmentRequest RRCConnectionReestablishmentRequest,
- rrcConnectionRequest RRCConnectionRequest
- },
- messageClassExtension SEQUENCE {}
-}
-
-
-UL-DCCH-Message ::= SEQUENCE {
- message UL-DCCH-MessageType
-}
-
-UL-DCCH-MessageType ::= CHOICE {
- c1 CHOICE {
- csfbParametersRequestCDMA2000 CSFBParametersRequestCDMA2000,
- measurementReport MeasurementReport,
- rrcConnectionReconfigurationComplete RRCConnectionReconfigurationComplete,
- rrcConnectionReestablishmentComplete RRCConnectionReestablishmentComplete,
- rrcConnectionSetupComplete RRCConnectionSetupComplete,
- securityModeComplete SecurityModeComplete,
- securityModeFailure SecurityModeFailure,
- ueCapabilityInformation UECapabilityInformation,
- ulHandoverPreparationTransfer ULHandoverPreparationTransfer,
- ulInformationTransfer ULInformationTransfer,
- counterCheckResponse CounterCheckResponse,
- spare5 NULL, spare4 NULL,
- spare3 NULL, spare2 NULL, spare1 NULL
- },
- messageClassExtension SEQUENCE {}
-}
-
-
-CounterCheck ::= SEQUENCE {
- rrc-TransactionIdentifier RRC-TransactionIdentifier,
- criticalExtensions CHOICE {
- c1 CHOICE {
- counterCheck-r8 CounterCheck-r8-IEs,
- spare3 NULL, spare2 NULL, spare1 NULL
- },
- criticalExtensionsFuture SEQUENCE {}
- }
-}
-
-CounterCheck-r8-IEs ::= SEQUENCE {
- drb-CountMSB-InfoList DRB-CountMSB-InfoList,
- nonCriticalExtension SEQUENCE {} OPTIONAL --Need OP
-}
-
-DRB-CountMSB-InfoList::= SEQUENCE (SIZE (1..maxDRB)) OF DRB-CountMSB-Info
-
-DRB-CountMSB-Info ::= SEQUENCE {
- drb-Identity DRB-Identity,
- countMSB-Uplink INTEGER(0..33554431),
- countMSB-Downlink INTEGER(0..33554431)
-}
-
-
-CounterCheckResponse ::= SEQUENCE {
- rrc-TransactionIdentifier RRC-TransactionIdentifier,
- criticalExtensions CHOICE {
- counterCheckResponse-r8 CounterCheckResponse-r8-IEs,
- criticalExtensionsFuture SEQUENCE {}
- }
-}
-
-CounterCheckResponse-r8-IEs ::= SEQUENCE {
- drb-CountInfoList DRB-CountInfoList,
- nonCriticalExtension SEQUENCE {} OPTIONAL
-}
-
-DRB-CountInfoList ::= SEQUENCE (SIZE (0..maxDRB)) OF DRB-CountInfo
-
-DRB-CountInfo ::= SEQUENCE {
- drb-Identity DRB-Identity,
- count-Uplink INTEGER(0..4294967295),
- count-Downlink INTEGER(0..4294967295)
-}
-
-
-CSFBParametersRequestCDMA2000 ::= SEQUENCE {
- criticalExtensions CHOICE {
- csfbParametersRequestCDMA2000-r8 CSFBParametersRequestCDMA2000-r8-IEs,
- criticalExtensionsFuture SEQUENCE {}
- }
-}
-
-CSFBParametersRequestCDMA2000-r8-IEs ::= SEQUENCE {
- nonCriticalExtension SEQUENCE {} OPTIONAL
-}
-
-CSFBParametersResponseCDMA2000 ::= SEQUENCE {
- rrc-TransactionIdentifier RRC-TransactionIdentifier,
- criticalExtensions CHOICE {
- csfbParametersResponseCDMA2000-r8 CSFBParametersResponseCDMA2000-r8-IEs,
- criticalExtensionsFuture SEQUENCE {}
- }
-}
-
-CSFBParametersResponseCDMA2000-r8-IEs ::= SEQUENCE {
- rand RAND-CDMA2000,
- mobilityParameters MobilityParametersCDMA2000,
- nonCriticalExtension SEQUENCE {} OPTIONAL --Need OP
-}
-
-
-DLInformationTransfer ::= SEQUENCE {
- rrc-TransactionIdentifier RRC-TransactionIdentifier,
- criticalExtensions CHOICE {
- c1 CHOICE {
- dlInformationTransfer-r8 DLInformationTransfer-r8-IEs,
- spare3 NULL, spare2 NULL, spare1 NULL
- },
- criticalExtensionsFuture SEQUENCE {}
- }
-}
-
-DLInformationTransfer-r8-IEs ::= SEQUENCE {
- dedicatedInfoType CHOICE {
- dedicatedInfoNAS DedicatedInfoNAS,
- dedicatedInfoCDMA2000-1XRTT DedicatedInfoCDMA2000,
- dedicatedInfoCDMA2000-HRPD DedicatedInfoCDMA2000
- },
- nonCriticalExtension SEQUENCE {} OPTIONAL --Need OP
-}
-
-
-HandoverFromEUTRAPreparationRequest ::= SEQUENCE {
- rrc-TransactionIdentifier RRC-TransactionIdentifier,
- criticalExtensions CHOICE {
- c1 CHOICE {
- handoverFromEUTRAPreparationRequest-r8
- HandoverFromEUTRAPreparationRequest-r8-IEs,
- spare3 NULL, spare2 NULL, spare1 NULL
- },
- criticalExtensionsFuture SEQUENCE {}
- }
-}
-
-HandoverFromEUTRAPreparationRequest-r8-IEs ::= SEQUENCE {
- cdma2000-Type CDMA2000-Type,
- rand RAND-CDMA2000 OPTIONAL, -- Cond cdma2000-Type
- mobilityParameters MobilityParametersCDMA2000 OPTIONAL, -- Cond cdma2000-Type
- nonCriticalExtension SEQUENCE {} OPTIONAL -- Need OP
-}
-
-
-MasterInformationBlock ::= SEQUENCE {
- dl-Bandwidth ENUMERATED {
- n6, n15, n25, n50, n75, n100},
- phich-Config PHICH-Config,
- systemFrameNumber BIT STRING (SIZE (8)),
- spare BIT STRING (SIZE (10))
-}
-
-
-
-MeasurementReport ::= SEQUENCE {
- criticalExtensions CHOICE {
- c1 CHOICE{
- measurementReport-r8 MeasurementReport-r8-IEs,
- spare7 NULL,
- spare6 NULL, spare5 NULL, spare4 NULL,
- spare3 NULL, spare2 NULL, spare1 NULL
- },
- criticalExtensionsFuture SEQUENCE {}
- }
-}
-
-MeasurementReport-r8-IEs ::= SEQUENCE {
- measResults MeasResults,
- nonCriticalExtension SEQUENCE {} OPTIONAL
-}
-
-
-MobilityFromEUTRACommand ::= SEQUENCE {
- rrc-TransactionIdentifier RRC-TransactionIdentifier,
- criticalExtensions CHOICE {
- c1 CHOICE{
- mobilityFromEUTRACommand-r8 MobilityFromEUTRACommand-r8-IEs,
- spare3 NULL, spare2 NULL, spare1 NULL
- },
- criticalExtensionsFuture SEQUENCE {}
- }
-}
-
-MobilityFromEUTRACommand-r8-IEs ::= SEQUENCE {
- cs-FallbackIndicator BOOLEAN,
- purpose CHOICE{
- handover Handover,
- cellChangeOrder CellChangeOrder
- },
- nonCriticalExtension SEQUENCE {} OPTIONAL -- Need OP
-}
-
-Handover ::= SEQUENCE {
- targetRAT-Type ENUMERATED {
- utra, geran, cdma2000-1XRTT, cdma2000-HRPD,
- spare4, spare3, spare2, spare1, ...},
- targetRAT-MessageContainer OCTET STRING,
- nas-SecurityParamFromEUTRA OCTET STRING (SIZE (1)) OPTIONAL, -- Cond UTRAGERAN
- systemInformation SI-OrPSI-GERAN OPTIONAL -- Cond PSHO
-}
-
-CellChangeOrder ::= SEQUENCE {
- t304 ENUMERATED {
- ms100, ms200, ms500, ms1000,
- ms2000, ms4000, ms8000, spare1},
- targetRAT-Type CHOICE {
- geran SEQUENCE {
- physCellId PhysCellIdGERAN,
- carrierFreq CarrierFreqGERAN,
- networkControlOrder BIT STRING (SIZE (2)) OPTIONAL, -- Need OP
- systemInformation SI-OrPSI-GERAN OPTIONAL -- Need OP
- },
- ...
- }
-}
-
-SI-OrPSI-GERAN ::= CHOICE {
- si SystemInfoListGERAN,
- psi SystemInfoListGERAN
-}
-
-SystemInfoListGERAN ::= SEQUENCE (SIZE (1..maxGERAN-SI)) OF
- OCTET STRING (SIZE (1..23))
-
-
-Paging ::= SEQUENCE {
- pagingRecordList PagingRecordList OPTIONAL, -- Need ON
- systemInfoModification ENUMERATED {true} OPTIONAL, -- Need ON
- etws-Indication ENUMERATED {true} OPTIONAL, -- Need ON
- nonCriticalExtension SEQUENCE {} OPTIONAL -- Need OP
-}
-
-PagingRecordList ::= SEQUENCE (SIZE (1..maxPageRec)) OF PagingRecord
-
-PagingRecord ::= SEQUENCE {
- ue-Identity PagingUE-Identity,
- cn-Domain ENUMERATED {ps, cs},
- ...
-}
-
-PagingUE-Identity ::= CHOICE {
- s-TMSI S-TMSI,
- imsi IMSI,
- ...
-}
-
-IMSI ::= SEQUENCE (SIZE (6..21)) OF IMSI-Digit
-
-IMSI-Digit::= INTEGER (0..9)
-
-
-RRCConnectionReconfiguration ::= SEQUENCE {
- rrc-TransactionIdentifier RRC-TransactionIdentifier,
- criticalExtensions CHOICE {
- c1 CHOICE{
- rrcConnectionReconfiguration-r8 RRCConnectionReconfiguration-r8-IEs,
- spare7 NULL,
- spare6 NULL, spare5 NULL, spare4 NULL,
- spare3 NULL, spare2 NULL, spare1 NULL
- },
- criticalExtensionsFuture SEQUENCE {}
- }
-}
-
-RRCConnectionReconfiguration-r8-IEs ::= SEQUENCE {
- measConfig MeasConfig OPTIONAL, -- Need ON
- mobilityControlInfo MobilityControlInfo OPTIONAL, -- Cond HO
- dedicatedInfoNASList SEQUENCE (SIZE(1..maxDRB)) OF
- DedicatedInfoNAS OPTIONAL, -- Cond nonHO
- radioResourceConfigDedicated RadioResourceConfigDedicated OPTIONAL, -- Cond HO-toEUTRA
- securityConfigHO SecurityConfigHO OPTIONAL, -- Cond HO
- nonCriticalExtension SEQUENCE {} OPTIONAL -- Need OP
-}
-
-SecurityConfigHO ::= SEQUENCE {
- handoverType CHOICE {
- intraLTE SEQUENCE {
- securityAlgorithmConfig SecurityAlgorithmConfig OPTIONAL, -- Need OP
- keyChangeIndicator BOOLEAN,
- nextHopChainingCount NextHopChainingCount
- },
- interRAT SEQUENCE {
- securityAlgorithmConfig SecurityAlgorithmConfig,
- nas-SecurityParamToEUTRA OCTET STRING (SIZE(6))
- }
- },
- ...
-}
-
-
-RRCConnectionReconfigurationComplete ::= SEQUENCE {
- rrc-TransactionIdentifier RRC-TransactionIdentifier,
- criticalExtensions CHOICE {
- rrcConnectionReconfigurationComplete-r8
- RRCConnectionReconfigurationComplete-r8-IEs,
- criticalExtensionsFuture SEQUENCE {}
- }
-}
-
-RRCConnectionReconfigurationComplete-r8-IEs ::= SEQUENCE {
- nonCriticalExtension SEQUENCE {} OPTIONAL
-}
-
-
-RRCConnectionReestablishment ::= SEQUENCE {
- rrc-TransactionIdentifier RRC-TransactionIdentifier,
- criticalExtensions CHOICE {
- c1 CHOICE{
- rrcConnectionReestablishment-r8 RRCConnectionReestablishment-r8-IEs,
- spare7 NULL,
- spare6 NULL, spare5 NULL, spare4 NULL,
- spare3 NULL, spare2 NULL, spare1 NULL
- },
- criticalExtensionsFuture SEQUENCE {}
- }
-}
-
-RRCConnectionReestablishment-r8-IEs ::= SEQUENCE {
- radioResourceConfigDedicated RadioResourceConfigDedicated,
- nextHopChainingCount NextHopChainingCount,
- nonCriticalExtension SEQUENCE {} OPTIONAL -- Need OP
-}
-
-
-RRCConnectionReestablishmentComplete ::= SEQUENCE {
- rrc-TransactionIdentifier RRC-TransactionIdentifier,
- criticalExtensions CHOICE {
- rrcConnectionReestablishmentComplete-r8
- RRCConnectionReestablishmentComplete-r8-IEs,
- criticalExtensionsFuture SEQUENCE {}
- }
-}
-
-RRCConnectionReestablishmentComplete-r8-IEs ::= SEQUENCE {
- nonCriticalExtension SEQUENCE {} OPTIONAL
-}
-
-
-RRCConnectionReestablishmentReject ::= SEQUENCE {
- criticalExtensions CHOICE {
- rrcConnectionReestablishmentReject-r8
- RRCConnectionReestablishmentReject-r8-IEs,
- criticalExtensionsFuture SEQUENCE {}
- }
-}
-
-RRCConnectionReestablishmentReject-r8-IEs ::= SEQUENCE {
- nonCriticalExtension SEQUENCE {} OPTIONAL -- Need OP
-}
-
-
-RRCConnectionReestablishmentRequest ::= SEQUENCE {
- criticalExtensions CHOICE {
- rrcConnectionReestablishmentRequest-r8
- RRCConnectionReestablishmentRequest-r8-IEs,
- criticalExtensionsFuture SEQUENCE {}
- }
-}
-
-RRCConnectionReestablishmentRequest-r8-IEs ::= SEQUENCE {
- ue-Identity ReestabUE-Identity,
- reestablishmentCause ReestablishmentCause,
- spare BIT STRING (SIZE (2))
-}
-
-ReestabUE-Identity ::= SEQUENCE {
- c-RNTI C-RNTI,
- physCellId PhysCellId,
- shortMAC-I ShortMAC-I
-}
-
-ReestablishmentCause ::= ENUMERATED {
- reconfigurationFailure, handoverFailure,
- otherFailure, spare1}
-
-
-RRCConnectionReject ::= SEQUENCE {
- criticalExtensions CHOICE {
- c1 CHOICE {
- rrcConnectionReject-r8 RRCConnectionReject-r8-IEs,
- spare3 NULL, spare2 NULL, spare1 NULL
- },
- criticalExtensionsFuture SEQUENCE {}
- }
-}
-
-RRCConnectionReject-r8-IEs ::= SEQUENCE {
- waitTime INTEGER (1..16),
- nonCriticalExtension SEQUENCE {} OPTIONAL -- Need OP
-}
-
-
-RRCConnectionRelease ::= SEQUENCE {
- rrc-TransactionIdentifier RRC-TransactionIdentifier,
- criticalExtensions CHOICE {
- c1 CHOICE {
- rrcConnectionRelease-r8 RRCConnectionRelease-r8-IEs,
- spare3 NULL, spare2 NULL, spare1 NULL
- },
- criticalExtensionsFuture SEQUENCE {}
- }
-}
-
-RRCConnectionRelease-r8-IEs ::= SEQUENCE {
- releaseCause ReleaseCause,
- redirectedCarrierInfo RedirectedCarrierInfo OPTIONAL, -- Need ON
- idleModeMobilityControlInfo IdleModeMobilityControlInfo OPTIONAL, -- Need OP
- nonCriticalExtension SEQUENCE {} OPTIONAL -- Need OP
-}
-
-ReleaseCause ::= ENUMERATED {loadBalancingTAUrequired,
- other,spare2, spare1 }
-
-RedirectedCarrierInfo ::= CHOICE {
- eutra ARFCN-ValueEUTRA,
- geran CarrierFreqsGERAN,
- utra-FDD ARFCN-ValueUTRA,
- utra-TDD ARFCN-ValueUTRA,
- cdma2000-HRPD CarrierFreqCDMA2000,
- cdma2000-1xRTT CarrierFreqCDMA2000,
- ...
-}
-
-IdleModeMobilityControlInfo ::= SEQUENCE {
- freqPriorityListEUTRA FreqPriorityListEUTRA OPTIONAL, -- Need ON
- freqPriorityListGERAN FreqsPriorityListGERAN OPTIONAL, -- Need ON
- freqPriorityListUTRA-FDD FreqPriorityListUTRA-FDD OPTIONAL, -- Need ON
- freqPriorityListUTRA-TDD FreqPriorityListUTRA-TDD OPTIONAL, -- Need ON
- bandClassPriorityListHRPD BandClassPriorityListHRPD OPTIONAL, -- Need ON
- bandClassPriorityList1XRTT BandClassPriorityList1XRTT OPTIONAL, -- Need ON
- t320 ENUMERATED {
- min5, min10, min20, min30, min60, min120, min180,
- spare1} OPTIONAL, -- Need OR
- ...
-}
-
-FreqPriorityListEUTRA ::= SEQUENCE (SIZE (1..maxFreq)) OF FreqPriorityEUTRA
-
-FreqPriorityEUTRA ::= SEQUENCE {
- carrierFreq ARFCN-ValueEUTRA,
- cellReselectionPriority CellReselectionPriority
-}
-
-FreqsPriorityListGERAN ::= SEQUENCE (SIZE (1..maxGNFG)) OF FreqsPriorityGERAN
-
-FreqsPriorityGERAN ::= SEQUENCE {
- carrierFreqs CarrierFreqsGERAN,
- cellReselectionPriority CellReselectionPriority
-}
-
-FreqPriorityListUTRA-FDD ::= SEQUENCE (SIZE (1..maxUTRA-FDD-Carrier)) OF FreqPriorityUTRA-FDD
-
-FreqPriorityUTRA-FDD ::= SEQUENCE {
- carrierFreq ARFCN-ValueUTRA,
- cellReselectionPriority CellReselectionPriority
-}
-
-FreqPriorityListUTRA-TDD ::= SEQUENCE (SIZE (1..maxUTRA-TDD-Carrier)) OF FreqPriorityUTRA-TDD
-
-FreqPriorityUTRA-TDD ::= SEQUENCE {
- carrierFreq ARFCN-ValueUTRA,
- cellReselectionPriority CellReselectionPriority
-}
-
-BandClassPriorityListHRPD ::= SEQUENCE (SIZE (1..maxCDMA-BandClass)) OF BandClassPriorityHRPD
-
-BandClassPriorityHRPD ::= SEQUENCE {
- bandClass BandclassCDMA2000,
- cellReselectionPriority CellReselectionPriority
-}
-
-BandClassPriorityList1XRTT ::= SEQUENCE (SIZE (1..maxCDMA-BandClass)) OF BandClassPriority1XRTT
-
-BandClassPriority1XRTT ::= SEQUENCE {
- bandClass BandclassCDMA2000,
- cellReselectionPriority CellReselectionPriority
-}
-
-RRCConnectionRequest ::= SEQUENCE {
- criticalExtensions CHOICE {
- rrcConnectionRequest-r8 RRCConnectionRequest-r8-IEs,
- criticalExtensionsFuture SEQUENCE {}
- }
-}
-
-RRCConnectionRequest-r8-IEs ::= SEQUENCE {
- ue-Identity InitialUE-Identity,
- establishmentCause EstablishmentCause,
- spare BIT STRING (SIZE (1))
-}
-
-InitialUE-Identity ::= CHOICE {
- s-TMSI S-TMSI,
- randomValue BIT STRING (SIZE (40))
-}
-
-EstablishmentCause ::= ENUMERATED {
- emergency, highPriorityAccess, mt-Access, mo-Signalling,
- mo-Data, spare3, spare2, spare1}
-
-
-RRCConnectionSetup ::= SEQUENCE {
- rrc-TransactionIdentifier RRC-TransactionIdentifier,
- criticalExtensions CHOICE {
- c1 CHOICE {
- rrcConnectionSetup-r8 RRCConnectionSetup-r8-IEs,
- spare7 NULL,
- spare6 NULL, spare5 NULL, spare4 NULL,
- spare3 NULL, spare2 NULL, spare1 NULL
- },
- criticalExtensionsFuture SEQUENCE {}
- }
-}
-
-RRCConnectionSetup-r8-IEs ::= SEQUENCE {
- radioResourceConfigDedicated RadioResourceConfigDedicated,
- nonCriticalExtension SEQUENCE {} OPTIONAL -- Need OP
-}
-
-
-RRCConnectionSetupComplete ::= SEQUENCE {
- rrc-TransactionIdentifier RRC-TransactionIdentifier,
- criticalExtensions CHOICE {
- c1 CHOICE{
- rrcConnectionSetupComplete-r8 RRCConnectionSetupComplete-r8-IEs,
- spare3 NULL, spare2 NULL, spare1 NULL
- },
- criticalExtensionsFuture SEQUENCE {}
- }
-}
-
-RRCConnectionSetupComplete-r8-IEs ::= SEQUENCE {
- selectedPLMN-Identity INTEGER (1..6),
- registeredMME RegisteredMME OPTIONAL,
- dedicatedInfoNAS DedicatedInfoNAS,
- nonCriticalExtension SEQUENCE {} OPTIONAL
-}
-
-RegisteredMME ::= SEQUENCE {
- plmn-Identity PLMN-Identity OPTIONAL,
- mmegi BIT STRING (SIZE (16)),
- mmec MMEC
-}
-
-
-SecurityModeCommand ::= SEQUENCE {
- rrc-TransactionIdentifier RRC-TransactionIdentifier,
- criticalExtensions CHOICE {
- c1 CHOICE{
- securityModeCommand-r8 SecurityModeCommand-r8-IEs,
- spare3 NULL, spare2 NULL, spare1 NULL
- },
- criticalExtensionsFuture SEQUENCE {}
- }
-}
-
-SecurityModeCommand-r8-IEs ::= SEQUENCE {
- securityConfigSMC SecurityConfigSMC,
- nonCriticalExtension SEQUENCE {} OPTIONAL -- Need OP
-}
-
-SecurityConfigSMC ::= SEQUENCE {
- securityAlgorithmConfig SecurityAlgorithmConfig,
- ...
-}
-
-
-SecurityModeComplete ::= SEQUENCE {
- rrc-TransactionIdentifier RRC-TransactionIdentifier,
- criticalExtensions CHOICE {
- securityModeComplete-r8 SecurityModeComplete-r8-IEs,
- criticalExtensionsFuture SEQUENCE {}
- }
-}
-
-SecurityModeComplete-r8-IEs ::= SEQUENCE {
- nonCriticalExtension SEQUENCE {} OPTIONAL
-}
-
-
-SecurityModeFailure ::= SEQUENCE {
- rrc-TransactionIdentifier RRC-TransactionIdentifier,
- criticalExtensions CHOICE {
- securityModeFailure-r8 SecurityModeFailure-r8-IEs,
- criticalExtensionsFuture SEQUENCE {}
- }
-}
-
-SecurityModeFailure-r8-IEs ::= SEQUENCE {
- nonCriticalExtension SEQUENCE {} OPTIONAL
-}
-
-
-SystemInformation ::= SEQUENCE {
- criticalExtensions CHOICE {
- systemInformation-r8 SystemInformation-r8-IEs,
- criticalExtensionsFuture SEQUENCE {}
- }
-}
-SystemInformation-r8-IEs ::= SEQUENCE {
- sib-TypeAndInfo SEQUENCE (SIZE (1..maxSIB)) OF CHOICE {
- sib2 SystemInformationBlockType2,
- sib3 SystemInformationBlockType3,
- sib4 SystemInformationBlockType4,
- sib5 SystemInformationBlockType5,
- sib6 SystemInformationBlockType6,
- sib7 SystemInformationBlockType7,
- sib8 SystemInformationBlockType8,
- sib9 SystemInformationBlockType9,
- sib10 SystemInformationBlockType10,
- sib11 SystemInformationBlockType11,
- ...
- },
- nonCriticalExtension SEQUENCE {} OPTIONAL -- Need OP
-}
-
-
-SystemInformationBlockType1 ::= SEQUENCE {
- cellAccessRelatedInfo SEQUENCE {
- plmn-IdentityList PLMN-IdentityList,
- trackingAreaCode TrackingAreaCode,
- cellIdentity CellIdentity,
- cellBarred ENUMERATED {barred, notBarred},
- intraFreqReselection ENUMERATED {allowed, notAllowed},
- csg-Indication BOOLEAN,
- csg-Identity BIT STRING (SIZE (27)) OPTIONAL -- Need OR
- },
- cellSelectionInfo SEQUENCE {
- q-RxLevMin Q-RxLevMin,
- q-RxLevMinOffset INTEGER (1..8) OPTIONAL -- Need OP
- },
- p-Max P-Max OPTIONAL, -- Need OP
- freqBandIndicator INTEGER (1..64),
- schedulingInfoList SchedulingInfoList,
- tdd-Config TDD-Config OPTIONAL, -- Cond TDD
- si-WindowLength ENUMERATED {
- ms1, ms2, ms5, ms10, ms15, ms20,
- ms40},
- systemInfoValueTag INTEGER (0..31),
- nonCriticalExtension SEQUENCE {} OPTIONAL -- Need OP
-}
-
-PLMN-IdentityList ::= SEQUENCE (SIZE (1..6)) OF PLMN-IdentityInfo
-
-PLMN-IdentityInfo ::= SEQUENCE {
- plmn-Identity PLMN-Identity,
- cellReservedForOperatorUse ENUMERATED {reserved, notReserved}
-}
-
-SchedulingInfoList ::= SEQUENCE (SIZE (1..maxSI-Message)) OF SchedulingInfo
-
-SchedulingInfo ::= SEQUENCE {
- si-Periodicity ENUMERATED {
- rf8, rf16, rf32, rf64, rf128, rf256, rf512},
- sib-MappingInfo SIB-MappingInfo
-}
-
-SIB-MappingInfo ::= SEQUENCE (SIZE (0..maxSIB-1)) OF SIB-Type
-
-SIB-Type ::= ENUMERATED {
- sibType3, sibType4, sibType5, sibType6,
- sibType7, sibType8, sibType9, sibType10,
- sibType11, spare7, spare6, spare5,
- spare4, spare3, spare2, spare1, ...}
-
-
-UECapabilityEnquiry ::= SEQUENCE {
- rrc-TransactionIdentifier RRC-TransactionIdentifier,
- criticalExtensions CHOICE {
- c1 CHOICE {
- ueCapabilityEnquiry-r8 UECapabilityEnquiry-r8-IEs,
- spare3 NULL, spare2 NULL, spare1 NULL
- },
- criticalExtensionsFuture SEQUENCE {}
- }
-}
-
-UECapabilityEnquiry-r8-IEs ::= SEQUENCE {
- ue-CapabilityRequest UE-CapabilityRequest,
- nonCriticalExtension SEQUENCE {} OPTIONAL -- Need OP
-}
-
-UE-CapabilityRequest ::= SEQUENCE (SIZE (1..maxRAT-Capabilities)) OF RAT-Type
-
-
-UECapabilityInformation ::= SEQUENCE {
- rrc-TransactionIdentifier RRC-TransactionIdentifier,
- criticalExtensions CHOICE {
- c1 CHOICE{
- ueCapabilityInformation-r8 UECapabilityInformation-r8-IEs,
- spare7 NULL,
- spare6 NULL, spare5 NULL, spare4 NULL,
- spare3 NULL, spare2 NULL, spare1 NULL
- },
- criticalExtensionsFuture SEQUENCE {}
- }
-}
-
-UECapabilityInformation-r8-IEs ::= SEQUENCE {
- ue-CapabilityRAT-ContainerList UE-CapabilityRAT-ContainerList,
- nonCriticalExtension SEQUENCE {} OPTIONAL
-}
-
-
-ULHandoverPreparationTransfer ::= SEQUENCE {
- criticalExtensions CHOICE {
- c1 CHOICE {
- ulHandoverPreparationTransfer-r8 ULHandoverPreparationTransfer-r8-IEs,
- spare3 NULL, spare2 NULL, spare1 NULL
- },
- criticalExtensionsFuture SEQUENCE {}
- }
-}
-
-ULHandoverPreparationTransfer-r8-IEs ::= SEQUENCE {
- cdma2000-Type CDMA2000-Type,
- meid BIT STRING (SIZE (56)) OPTIONAL,
- dedicatedInfo DedicatedInfoCDMA2000,
- nonCriticalExtension SEQUENCE {} OPTIONAL
-}
-
-
-ULInformationTransfer ::= SEQUENCE {
- criticalExtensions CHOICE {
- c1 CHOICE {
- ulInformationTransfer-r8 ULInformationTransfer-r8-IEs,
- spare3 NULL, spare2 NULL, spare1 NULL
- },
- criticalExtensionsFuture SEQUENCE {}
- }
-}
-
-ULInformationTransfer-r8-IEs ::= SEQUENCE {
- dedicatedInfoType CHOICE {
- dedicatedInfoNAS DedicatedInfoNAS,
- dedicatedInfoCDMA2000-1XRTT DedicatedInfoCDMA2000,
- dedicatedInfoCDMA2000-HRPD DedicatedInfoCDMA2000
- },
- nonCriticalExtension SEQUENCE {} OPTIONAL
-}
-
-
-SystemInformationBlockType2 ::= SEQUENCE {
- ac-BarringInfo SEQUENCE {
- ac-BarringForEmergency BOOLEAN,
- ac-BarringForMO-Signalling AC-BarringConfig OPTIONAL, -- Need OP
- ac-BarringForMO-Data AC-BarringConfig OPTIONAL -- Need OP
- } OPTIONAL, -- Need OP
- radioResourceConfigCommon RadioResourceConfigCommonSIB,
- ue-TimersAndConstants UE-TimersAndConstants,
- freqInfo SEQUENCE {
- ul-CarrierFreq ARFCN-ValueEUTRA OPTIONAL, -- Need OP
- ul-Bandwidth ENUMERATED {n6, n15, n25, n50, n75, n100}
- OPTIONAL, -- Need OP
- additionalSpectrumEmission AdditionalSpectrumEmission
- },
- mbsfn-SubframeConfigList MBSFN-SubframeConfigList OPTIONAL, -- Need OR
- timeAlignmentTimerCommon TimeAlignmentTimer,
- ...
-}
-
-AC-BarringConfig ::= SEQUENCE {
- ac-BarringFactor ENUMERATED {
- p00, p05, p10, p15, p20, p25, p30, p40,
- p50, p60, p70, p75, p80, p85, p90, p95},
- ac-BarringTime ENUMERATED {s4, s8, s16, s32, s64, s128, s256, s512},
- ac-BarringForSpecialAC BIT STRING (SIZE(5))
-}
-
-MBSFN-SubframeConfigList ::= SEQUENCE (SIZE (1..maxMBSFN-Allocations)) OF MBSFN-SubframeConfig
-
-MBSFN-SubframeConfig ::= SEQUENCE {
- radioframeAllocationPeriod ENUMERATED {n1, n2, n4, n8, n16, n32},
- radioframeAllocationOffset INTEGER (0..7),
- subframeAllocation CHOICE {
- oneFrame BIT STRING (SIZE(6)),
- fourFrames BIT STRING (SIZE(24))
- }
-}
-
-SystemInformationBlockType3 ::= SEQUENCE {
- cellReselectionInfoCommon SEQUENCE {
- q-Hyst ENUMERATED {
- dB0, dB1, dB2, dB3, dB4, dB5, dB6, dB8, dB10,
- dB12, dB14, dB16, dB18, dB20, dB22, dB24},
- speedStateReselectionPars SEQUENCE {
- mobilityStateParameters MobilityStateParameters,
- q-HystSF SEQUENCE {
- sf-Medium ENUMERATED {
- dB-6, dB-4, dB-2, dB0},
- sf-High ENUMERATED {
- dB-6, dB-4, dB-2, dB0}
- }
- } OPTIONAL -- Need OP
- },
- cellReselectionServingFreqInfo SEQUENCE {
- s-NonIntraSearch ReselectionThreshold OPTIONAL, -- Need OP
- threshServingLow ReselectionThreshold,
- cellReselectionPriority CellReselectionPriority
- },
- intraFreqCellReselectionInfo SEQUENCE {
- q-RxLevMin Q-RxLevMin,
- p-Max P-Max OPTIONAL, -- Need OP
- s-IntraSearch ReselectionThreshold OPTIONAL, -- Need OP
- allowedMeasBandwidth AllowedMeasBandwidth OPTIONAL, -- Need OP
- presenceAntennaPort1 PresenceAntennaPort1,
- neighCellConfig NeighCellConfig,
- t-ReselectionEUTRA T-Reselection,
- t-ReselectionEUTRA-SF SpeedStateScaleFactors OPTIONAL -- Need OP
- },
- ...
-}
-
-
-SystemInformationBlockType4 ::= SEQUENCE {
- intraFreqNeighCellList IntraFreqNeighCellList OPTIONAL, -- Need OR
- intraFreqBlackCellList IntraFreqBlackCellList OPTIONAL, -- Need OR
- csg-PhysCellIdRange PhysCellIdRange OPTIONAL, -- Cond CSG
- ...
-}
-
-IntraFreqNeighCellList ::= SEQUENCE (SIZE (1..maxCellIntra)) OF IntraFreqNeighCellInfo
-
-IntraFreqNeighCellInfo ::= SEQUENCE {
- physCellId PhysCellId,
- q-OffsetCell Q-OffsetRange,
- ...
-}
-
-IntraFreqBlackCellList ::= SEQUENCE (SIZE (1..maxCellBlack)) OF PhysCellIdRange
-
-
-SystemInformationBlockType5 ::= SEQUENCE {
- interFreqCarrierFreqList InterFreqCarrierFreqList,
- ...
-}
-
-InterFreqCarrierFreqList ::= SEQUENCE (SIZE (1..maxFreq)) OF InterFreqCarrierFreqInfo
-
-InterFreqCarrierFreqInfo ::= SEQUENCE {
- dl-CarrierFreq ARFCN-ValueEUTRA,
- q-RxLevMin Q-RxLevMin,
- p-Max P-Max OPTIONAL, -- Need OP
- t-ReselectionEUTRA T-Reselection,
- t-ReselectionEUTRA-SF SpeedStateScaleFactors OPTIONAL, -- Need OP
- threshX-High ReselectionThreshold,
- threshX-Low ReselectionThreshold,
- allowedMeasBandwidth AllowedMeasBandwidth,
- presenceAntennaPort1 PresenceAntennaPort1,
- cellReselectionPriority CellReselectionPriority OPTIONAL, -- Need OP
- neighCellConfig NeighCellConfig,
- q-OffsetFreq Q-OffsetRange DEFAULT dB0,
- interFreqNeighCellList InterFreqNeighCellList OPTIONAL, -- Need OR
- interFreqBlackCellList InterFreqBlackCellList OPTIONAL, -- Need OR
- ...
-}
-
-InterFreqNeighCellList ::= SEQUENCE (SIZE (1..maxCellInter)) OF InterFreqNeighCellInfo
-
-InterFreqNeighCellInfo ::= SEQUENCE {
- physCellId PhysCellId,
- q-OffsetCell Q-OffsetRange
-}
-
-InterFreqBlackCellList ::= SEQUENCE (SIZE (1..maxCellBlack)) OF PhysCellIdRange
-
-
-SystemInformationBlockType6 ::= SEQUENCE {
- carrierFreqListUTRA-FDD CarrierFreqListUTRA-FDD OPTIONAL, -- Need OR
- carrierFreqListUTRA-TDD CarrierFreqListUTRA-TDD OPTIONAL, -- Need OR
- t-ReselectionUTRA T-Reselection,
- t-ReselectionUTRA-SF SpeedStateScaleFactors OPTIONAL, -- Need OP
- ...
-}
-
-CarrierFreqListUTRA-FDD ::= SEQUENCE (SIZE (1..maxUTRA-FDD-Carrier)) OF CarrierFreqUTRA-FDD
-
-CarrierFreqUTRA-FDD ::= SEQUENCE {
- carrierFreq ARFCN-ValueUTRA,
- cellReselectionPriority CellReselectionPriority OPTIONAL, -- Need OP
- threshX-High ReselectionThreshold,
- threshX-Low ReselectionThreshold,
- q-RxLevMin INTEGER (-60..-13),
- p-MaxUTRA INTEGER (-50..33),
- q-QualMin INTEGER (-24..0),
- ...
-}
-
-CarrierFreqListUTRA-TDD ::= SEQUENCE (SIZE (1..maxUTRA-TDD-Carrier)) OF CarrierFreqUTRA-TDD
-
-CarrierFreqUTRA-TDD ::= SEQUENCE {
- carrierFreq ARFCN-ValueUTRA,
- cellReselectionPriority CellReselectionPriority OPTIONAL, -- Need OP
- threshX-High ReselectionThreshold,
- threshX-Low ReselectionThreshold,
- q-RxLevMin INTEGER (-60..-13),
- p-MaxUTRA INTEGER (-50..33),
- ...
-}
-
-
-SystemInformationBlockType7 ::= SEQUENCE {
- t-ReselectionGERAN T-Reselection,
- t-ReselectionGERAN-SF SpeedStateScaleFactors OPTIONAL, -- Need OR
- carrierFreqsInfoList CarrierFreqsInfoListGERAN OPTIONAL, -- Need OR
- ...
-}
-
-CarrierFreqsInfoListGERAN ::= SEQUENCE (SIZE (1..maxGNFG)) OF CarrierFreqsInfoGERAN
-
-CarrierFreqsInfoGERAN ::= SEQUENCE {
- carrierFreqs CarrierFreqsGERAN,
- commonInfo SEQUENCE {
- cellReselectionPriority CellReselectionPriority OPTIONAL, -- Need OP
- ncc-Permitted BIT STRING (SIZE (8)),
- q-RxLevMin INTEGER (0..45),
- p-MaxGERAN INTEGER (0..39) OPTIONAL, -- Need OP
- threshX-High ReselectionThreshold,
- threshX-Low ReselectionThreshold
- },
- ...
-}
-
-
-SystemInformationBlockType8 ::= SEQUENCE {
- systemTimeInfo SystemTimeInfoCDMA2000 OPTIONAL, -- Need OR
- searchWindowSize INTEGER (0..15) OPTIONAL, -- Need OR
- parametersHRPD SEQUENCE {
- preRegistrationInfoHRPD PreRegistrationInfoHRPD,
- cellReselectionParametersHRPD CellReselectionParametersCDMA2000 OPTIONAL -- Need OR
- } OPTIONAL, -- Need OR
- parameters1XRTT SEQUENCE {
- csfb-RegistrationParam1XRTT CSFB-RegistrationParam1XRTT OPTIONAL, -- Need OP
- longCodeState1XRTT BIT STRING (SIZE (42)) OPTIONAL, -- Need OR
- cellReselectionParameters1XRTT CellReselectionParametersCDMA2000 OPTIONAL -- Need OR
- } OPTIONAL, -- Need OR
- ...
-}
-
-CellReselectionParametersCDMA2000 ::= SEQUENCE {
- bandClassList BandClassListCDMA2000,
- neighCellList NeighCellListCDMA2000,
- t-ReselectionCDMA2000 T-Reselection,
- t-ReselectionCDMA2000-SF SpeedStateScaleFactors OPTIONAL -- Need OP
-}
-NeighCellListCDMA2000 ::= SEQUENCE (SIZE (1..16)) OF NeighCellCDMA2000
-
-NeighCellCDMA2000 ::= SEQUENCE {
- bandClass BandclassCDMA2000,
- neighCellsPerFreqList NeighCellsPerBandclassListCDMA2000
-}
-
-NeighCellsPerBandclassListCDMA2000 ::= SEQUENCE (SIZE (1..16)) OF NeighCellsPerBandclassCDMA2000
-
-NeighCellsPerBandclassCDMA2000 ::= SEQUENCE {
- arfcn ARFCN-ValueCDMA2000,
- physCellIdList PhysCellIdListCDMA2000
-}
-
-PhysCellIdListCDMA2000 ::= SEQUENCE (SIZE (1..16)) OF PhysCellIdCDMA2000
-
-BandClassListCDMA2000 ::= SEQUENCE (SIZE (1..maxCDMA-BandClass)) OF BandClassInfoCDMA2000
-
-BandClassInfoCDMA2000 ::= SEQUENCE {
- bandClass BandclassCDMA2000,
- cellReselectionPriority CellReselectionPriority OPTIONAL, -- Need OP
- threshX-High INTEGER (0..63),
- threshX-Low INTEGER (0..63),
- ...
-}
-
-
-SystemInformationBlockType9 ::= SEQUENCE {
- hnb-Name OCTET STRING (SIZE(1..48)) OPTIONAL, -- Need OR
- ...
-}
-
-
-SystemInformationBlockType10 ::= SEQUENCE {
- messageIdentifier BIT STRING (SIZE (16)),
- serialNumber BIT STRING (SIZE (16)),
- warningType OCTET STRING (SIZE (2)),
- warningSecurityInfo OCTET STRING (SIZE (50)) OPTIONAL, -- Need OP
- ...
-}
-
-
-SystemInformationBlockType11 ::= SEQUENCE {
- messageIdentifier BIT STRING (SIZE (16)),
- serialNumber BIT STRING (SIZE (16)),
- warningMessageSegmentType ENUMERATED {notLastSegment, lastSegment},
- warningMessageSegmentNumber INTEGER (0..63),
- warningMessageSegment OCTET STRING,
- dataCodingScheme OCTET STRING (SIZE (1)) OPTIONAL, -- Cond Segment1
- ...
-}
-
-
-AntennaInfoCommon ::= SEQUENCE {
- antennaPortsCount ENUMERATED {an1, an2, an4, spare1}
-}
-
-AntennaInfoDedicated ::= SEQUENCE {
- transmissionMode ENUMERATED {
- tm1, tm2, tm3, tm4, tm5, tm6,
- tm7, spare1},
- codebookSubsetRestriction CHOICE {
- n2TxAntenna-tm3 BIT STRING (SIZE (2)),
- n4TxAntenna-tm3 BIT STRING (SIZE (4)),
- n2TxAntenna-tm4 BIT STRING (SIZE (6)),
- n4TxAntenna-tm4 BIT STRING (SIZE (64)),
- n2TxAntenna-tm5 BIT STRING (SIZE (4)),
- n4TxAntenna-tm5 BIT STRING (SIZE (16)),
- n2TxAntenna-tm6 BIT STRING (SIZE (4)),
- n4TxAntenna-tm6 BIT STRING (SIZE (16))
- } OPTIONAL, -- Cond TM
- ue-TransmitAntennaSelection CHOICE{
- release NULL,
- setup ENUMERATED {closedLoop, openLoop}
- }
-}
-
-
-CQI-ReportConfig ::= SEQUENCE {
- cqi-ReportModeAperiodic ENUMERATED {
- rm12, rm20, rm22, rm30, rm31,
- spare3, spare2, spare1} OPTIONAL, -- Need OR
- nomPDSCH-RS-EPRE-Offset INTEGER (-1..6),
- cqi-ReportPeriodic CQI-ReportPeriodic OPTIONAL -- Need ON
-}
-
-CQI-ReportPeriodic ::= CHOICE {
- release NULL,
- setup SEQUENCE {
- cqi-PUCCH-ResourceIndex INTEGER (0.. 1185),
- cqi-pmi-ConfigIndex INTEGER (0..1023),
- cqi-FormatIndicatorPeriodic CHOICE {
- widebandCQI NULL,
- subbandCQI SEQUENCE {
- k INTEGER (1..4)
- }
- },
- ri-ConfigIndex INTEGER (0..1023) OPTIONAL, -- Need OR
- simultaneousAckNackAndCQI BOOLEAN
- }
-}
-
-
-DRB-Identity ::= INTEGER (1..32)
-
-
-LogicalChannelConfig ::= SEQUENCE {
- ul-SpecificParameters SEQUENCE {
- priority INTEGER (1..16),
- prioritisedBitRate ENUMERATED {
- kBps0, kBps8, kBps16, kBps32, kBps64, kBps128,
- kBps256, infinity, spare8, spare7, spare6,
- spare5, spare4, spare3, spare2, spare1},
- bucketSizeDuration ENUMERATED {
- ms50, ms100, ms150, ms300, ms500, ms1000, spare2,
- spare1},
- logicalChannelGroup INTEGER (0..3) OPTIONAL -- Need OR
- } OPTIONAL, -- Cond UL
- ...
-}
-
-
-MAC-MainConfig ::= SEQUENCE {
- ul-SCH-Config SEQUENCE {
- maxHARQ-Tx ENUMERATED {
- n1, n2, n3, n4, n5, n6, n7, n8,
- n10, n12, n16, n20, n24, n28,
- spare2, spare1} OPTIONAL, -- Need ON
- periodicBSR-Timer ENUMERATED {
- sf5, sf10, sf16, sf20, sf32, sf40, sf64, sf80,
- sf128, sf160, sf320, sf640, sf1280, sf2560,
- infinity, spare1} OPTIONAL, -- Need ON
- retxBSR-Timer ENUMERATED {
- sf320, sf640, sf1280, sf2560, sf5120,
- sf10240, spare2, spare1},
- ttiBundling BOOLEAN
- } OPTIONAL, -- Need ON
- drx-Config DRX-Config OPTIONAL, -- Need ON
- timeAlignmentTimerDedicated TimeAlignmentTimer,
- phr-Config CHOICE {
- release NULL,
- setup SEQUENCE {
- periodicPHR-Timer ENUMERATED {sf10, sf20, sf50, sf100, sf200,
- sf500, sf1000, infinity},
- prohibitPHR-Timer ENUMERATED {sf0, sf10, sf20, sf50, sf100,
- sf200, sf500, sf1000},
- dl-PathlossChange ENUMERATED {dB1, dB3, dB6, infinity}
- }
- } OPTIONAL, -- Need ON
- ...
-}
-
-DRX-Config ::= CHOICE {
- release NULL,
- setup SEQUENCE {
- onDurationTimer ENUMERATED {
- psf1, psf2, psf3, psf4, psf5, psf6,
- psf8, psf10, psf20, psf30, psf40,
- psf50, psf60, psf80, psf100,
- psf200},
- drx-InactivityTimer ENUMERATED {
- psf1, psf2, psf3, psf4, psf5, psf6,
- psf8, psf10, psf20, psf30, psf40,
- psf50, psf60, psf80, psf100,
- psf200, psf300, psf500, psf750,
- psf1280, psf1920, psf2560, spare10,
- spare9, spare8, spare7, spare6,
- spare5, spare4, spare3, spare2,
- spare1},
- drx-RetransmissionTimer ENUMERATED {
- psf1, psf2, psf4, psf6, psf8, psf16,
- psf24, psf33},
- longDRX-CycleStartOffset CHOICE {
- sf10 INTEGER(0..9),
- sf20 INTEGER(0..19),
- sf32 INTEGER(0..31),
- sf40 INTEGER(0..39),
- sf64 INTEGER(0..63),
- sf80 INTEGER(0..79),
- sf128 INTEGER(0..127),
- sf160 INTEGER(0..159),
- sf256 INTEGER(0..255),
- sf320 INTEGER(0..319),
- sf512 INTEGER(0..511),
- sf640 INTEGER(0..639),
- sf1024 INTEGER(0..1023),
- sf1280 INTEGER(0..1279),
- sf2048 INTEGER(0..2047),
- sf2560 INTEGER(0..2559)
- },
- shortDRX SEQUENCE {
- shortDRX-Cycle ENUMERATED {
- sf2, sf5, sf8, sf10, sf16, sf20,
- sf32, sf40, sf64, sf80, sf128, sf160,
- sf256, sf320, sf512, sf640},
- drxShortCycleTimer INTEGER (1..16)
- } OPTIONAL -- Need OR
- }
-}
-
-
-PDCP-Config ::= SEQUENCE {
- discardTimer ENUMERATED {
- ms50, ms100, ms150, ms300, ms500,
- ms750, ms1500, infinity
- } OPTIONAL, -- Cond Setup
- rlc-AM SEQUENCE {
- statusReportRequired BOOLEAN
- } OPTIONAL, -- Cond Rlc-AM
- rlc-UM SEQUENCE {
- pdcp-SN-Size ENUMERATED {len7bits, len12bits}
- } OPTIONAL, -- Cond Rlc-UM
- headerCompression CHOICE {
- notUsed NULL,
- rohc SEQUENCE {
- maxCID INTEGER (1..16383) DEFAULT 15,
- profiles SEQUENCE {
- profile0x0001 BOOLEAN,
- profile0x0002 BOOLEAN,
- profile0x0003 BOOLEAN,
- profile0x0004 BOOLEAN,
- profile0x0006 BOOLEAN,
- profile0x0101 BOOLEAN,
- profile0x0102 BOOLEAN,
- profile0x0103 BOOLEAN,
- profile0x0104 BOOLEAN
- },
- ...
- }
- },
- ...
-}
-
-
-PDSCH-ConfigCommon::= SEQUENCE {
- referenceSignalPower INTEGER (-60..50),
- p-b INTEGER (0..3)
-}
-
-PDSCH-ConfigDedicated::= SEQUENCE {
- p-a ENUMERATED {
- dB-6, dB-4dot77, dB-3, dB-1dot77,
- dB0, dB1, dB2, dB3 }
-}
-
-
-PHICH-Config ::= SEQUENCE {
- phich-Duration ENUMERATED {normal, extended},
- phich-Resource ENUMERATED {oneSixth, half, one, two}
-}
-
-
-PhysicalConfigDedicated ::= SEQUENCE {
- pdsch-ConfigDedicated PDSCH-ConfigDedicated OPTIONAL, -- Need ON
- pucch-ConfigDedicated PUCCH-ConfigDedicated OPTIONAL, -- Need ON
- pusch-ConfigDedicated PUSCH-ConfigDedicated OPTIONAL, -- Need ON
- uplinkPowerControlDedicated UplinkPowerControlDedicated OPTIONAL, -- Need ON
- tpc-PDCCH-ConfigPUCCH TPC-PDCCH-Config OPTIONAL, -- Need ON
- tpc-PDCCH-ConfigPUSCH TPC-PDCCH-Config OPTIONAL, -- Need ON
- cqi-ReportConfig CQI-ReportConfig OPTIONAL, -- Need ON
- soundingRS-UL-ConfigDedicated SoundingRS-UL-ConfigDedicated OPTIONAL, -- Need ON
- antennaInfo CHOICE {
- explicitValue AntennaInfoDedicated,
- defaultValue NULL
- } OPTIONAL, -- Need ON
- schedulingRequestConfig SchedulingRequestConfig OPTIONAL, -- Need ON
- ...
-}
-
-
-P-Max ::= INTEGER (-30..33)
-
-
-PRACH-ConfigSIB ::= SEQUENCE {
- rootSequenceIndex INTEGER (0..837),
- prach-ConfigInfo PRACH-ConfigInfo
-}
-
-PRACH-Config ::= SEQUENCE {
- rootSequenceIndex INTEGER (0..837),
- prach-ConfigInfo PRACH-ConfigInfo OPTIONAL -- Need ON
-}
-
-PRACH-ConfigInfo ::= SEQUENCE {
- prach-ConfigIndex INTEGER (0..63),
- highSpeedFlag BOOLEAN,
- zeroCorrelationZoneConfig INTEGER (0..15),
- prach-FreqOffset INTEGER (0..94)
-}
-
-
-PresenceAntennaPort1 ::= BOOLEAN
-
-
-PUCCH-ConfigCommon ::= SEQUENCE {
- deltaPUCCH-Shift ENUMERATED {ds1, ds2, ds3},
- nRB-CQI INTEGER (0..98),
- nCS-AN INTEGER (0..7),
- n1PUCCH-AN INTEGER (0..2047)
-}
-
-PUCCH-ConfigDedicated ::= SEQUENCE {
- ackNackRepetition CHOICE{
- release NULL,
- setup SEQUENCE {
- repetitionFactor ENUMERATED { n2, n4, n6, spare1},
- n1PUCCH-AN-Rep INTEGER (0..2047)
- }
- },
- tdd-AckNackFeedbackMode ENUMERATED {bundling, multiplexing} OPTIONAL -- Cond TDD
-}
-
-
-PUSCH-ConfigCommon ::= SEQUENCE {
- pusch-ConfigBasic SEQUENCE {
- n-SB INTEGER (1..4),
- hoppingMode ENUMERATED {interSubFrame, intraAndInterSubFrame},
- pusch-HoppingOffset INTEGER (0..98),
- enable64QAM BOOLEAN
- },
- ul-ReferenceSignalsPUSCH UL-ReferenceSignalsPUSCH
-}
-
-PUSCH-ConfigDedicated ::= SEQUENCE {
- betaOffset-ACK-Index INTEGER (0..15),
- betaOffset-RI-Index INTEGER (0..15),
- betaOffset-CQI-Index INTEGER (0..15)
-}
-
-UL-ReferenceSignalsPUSCH ::= SEQUENCE {
- groupHoppingEnabled BOOLEAN,
- groupAssignmentPUSCH INTEGER (0..29),
- sequenceHoppingEnabled BOOLEAN,
- cyclicShift INTEGER (0..7)
-}
-
-
-RACH-ConfigCommon ::= SEQUENCE {
- preambleInfo SEQUENCE {
- numberOfRA-Preambles ENUMERATED {
- n4, n8, n12, n16 ,n20, n24, n28,
- n32, n36, n40, n44, n48, n52, n56,
- n60, n64},
- preamblesGroupAConfig SEQUENCE {
- sizeOfRA-PreamblesGroupA ENUMERATED {
- n4, n8, n12, n16 ,n20, n24, n28,
- n32, n36, n40, n44, n48, n52, n56,
- n60},
- messageSizeGroupA ENUMERATED {b56, b144, b208, b256},
- messagePowerOffsetGroupB ENUMERATED {
- minusinfinity, dB0, dB5, dB8, dB10, dB12,
- dB15, dB18},
- ...
- } OPTIONAL -- Need OP
- },
- powerRampingParameters SEQUENCE {
- powerRampingStep ENUMERATED {dB0, dB2,dB4, dB6},
- preambleInitialReceivedTargetPower ENUMERATED {
- dBm-120, dBm-118, dBm-116, dBm-114, dBm-112,
- dBm-110, dBm-108, dBm-106, dBm-104, dBm-102,
- dBm-100, dBm-98, dBm-96, dBm-94,
- dBm-92, dBm-90}
- },
- ra-SupervisionInfo SEQUENCE {
- preambleTransMax ENUMERATED {
- n3, n4, n5, n6, n7, n8, n10, n20, n50,
- n100, n200},
- ra-ResponseWindowSize ENUMERATED {
- sf2, sf3, sf4, sf5, sf6, sf7,
- sf8, sf10},
- mac-ContentionResolutionTimer ENUMERATED {
- sf8, sf16, sf24, sf32, sf40, sf48,
- sf56, sf64}
- },
- maxHARQ-Msg3Tx INTEGER (1..8),
- ...
-}
-
-
-RACH-ConfigDedicated ::= SEQUENCE {
- ra-PreambleIndex INTEGER (0..63),
- ra-PRACH-MaskIndex INTEGER (0..15)
-}
-
-
-RadioResourceConfigCommonSIB ::= SEQUENCE {
- rach-ConfigCommon RACH-ConfigCommon,
- bcch-Config BCCH-Config,
- pcch-Config PCCH-Config,
- prach-Config PRACH-ConfigSIB,
- pdsch-ConfigCommon PDSCH-ConfigCommon,
- pusch-ConfigCommon PUSCH-ConfigCommon,
- pucch-ConfigCommon PUCCH-ConfigCommon,
- soundingRS-UL-ConfigCommon SoundingRS-UL-ConfigCommon,
- uplinkPowerControlCommon UplinkPowerControlCommon,
- ul-CyclicPrefixLength UL-CyclicPrefixLength,
- ...
-}
-
-RadioResourceConfigCommon ::= SEQUENCE {
- rach-ConfigCommon RACH-ConfigCommon OPTIONAL, -- Need ON
- prach-Config PRACH-Config,
- pdsch-ConfigCommon PDSCH-ConfigCommon OPTIONAL, -- Need ON
- pusch-ConfigCommon PUSCH-ConfigCommon,
- phich-Config PHICH-Config OPTIONAL, -- Need ON
- pucch-ConfigCommon PUCCH-ConfigCommon OPTIONAL, -- Need ON
- soundingRS-UL-ConfigCommon SoundingRS-UL-ConfigCommon OPTIONAL, -- Need ON
- uplinkPowerControlCommon UplinkPowerControlCommon OPTIONAL, -- Need ON
- antennaInfoCommon AntennaInfoCommon OPTIONAL, -- Need ON
- p-Max P-Max OPTIONAL, -- Need OP
- tdd-Config TDD-Config OPTIONAL, -- Cond TDD
- ul-CyclicPrefixLength UL-CyclicPrefixLength,
- ...
-}
-
-BCCH-Config ::= SEQUENCE {
- modificationPeriodCoeff ENUMERATED {n2, n4, n8, n16}
-}
-
-PCCH-Config ::= SEQUENCE {
- defaultPagingCycle ENUMERATED {
- rf32, rf64, rf128, rf256},
- nB ENUMERATED {
- fourT, twoT, oneT, halfT, quarterT, oneEighthT,
- oneSixteenthT, oneThirtySecondT}
-}
-
-UL-CyclicPrefixLength ::= ENUMERATED {len1, len2}
-
-
-RadioResourceConfigDedicated ::= SEQUENCE {
- srb-ToAddModList SRB-ToAddModList OPTIONAL, -- Cond HO-Conn
- drb-ToAddModList DRB-ToAddModList OPTIONAL, -- Cond HO-toEUTRA
- drb-ToReleaseList DRB-ToReleaseList OPTIONAL, -- Need ON
- mac-MainConfig CHOICE {
- explicitValue MAC-MainConfig,
- defaultValue NULL
- } OPTIONAL, -- Cond HO-toEUTRA2
- sps-Config SPS-Config OPTIONAL, -- Need ON
- physicalConfigDedicated PhysicalConfigDedicated OPTIONAL, -- Need ON
- ...
-}
-
-SRB-ToAddModList ::= SEQUENCE (SIZE (1..2)) OF SRB-ToAddMod
-
-SRB-ToAddMod ::= SEQUENCE {
- srb-Identity INTEGER (1..2),
- rlc-Config CHOICE {
- explicitValue RLC-Config,
- defaultValue NULL
- } OPTIONAL, -- Cond Setup
- logicalChannelConfig CHOICE {
- explicitValue LogicalChannelConfig,
- defaultValue NULL
- } OPTIONAL, -- Cond Setup
- ...
-}
-
-DRB-ToAddModList ::= SEQUENCE (SIZE (1..maxDRB)) OF DRB-ToAddMod
-
-DRB-ToAddMod ::= SEQUENCE {
- eps-BearerIdentity INTEGER (0..15) OPTIONAL, -- Cond DRB-Setup
- drb-Identity DRB-Identity,
- pdcp-Config PDCP-Config OPTIONAL, -- Cond PDCP
- rlc-Config RLC-Config OPTIONAL, -- Cond Setup
- logicalChannelIdentity INTEGER (3..10) OPTIONAL, -- Cond DRB-Setup
- logicalChannelConfig LogicalChannelConfig OPTIONAL, -- Cond Setup
- ...
-}
-
-DRB-ToReleaseList ::= SEQUENCE (SIZE (1..maxDRB)) OF DRB-Identity
-
-
-RLC-Config ::= CHOICE {
- am SEQUENCE {
- ul-AM-RLC UL-AM-RLC,
- dl-AM-RLC DL-AM-RLC
- },
- um-Bi-Directional SEQUENCE {
- ul-UM-RLC UL-UM-RLC,
- dl-UM-RLC DL-UM-RLC
- },
- um-Uni-Directional-UL SEQUENCE {
- ul-UM-RLC UL-UM-RLC
- },
- um-Uni-Directional-DL SEQUENCE {
- dl-UM-RLC DL-UM-RLC
- },
- ...
-}
-
-UL-AM-RLC ::= SEQUENCE {
- t-PollRetransmit T-PollRetransmit,
- pollPDU PollPDU,
- pollByte PollByte,
- maxRetxThreshold ENUMERATED {
- t1, t2, t3, t4, t6, t8, t16, t32}
-}
-
-DL-AM-RLC ::= SEQUENCE {
- t-Reordering T-Reordering,
- t-StatusProhibit T-StatusProhibit
-}
-
-UL-UM-RLC ::= SEQUENCE {
- sn-FieldLength SN-FieldLength
-}
-
-DL-UM-RLC ::= SEQUENCE {
- sn-FieldLength SN-FieldLength,
- t-Reordering T-Reordering
-}
-
-SN-FieldLength ::= ENUMERATED {size5, size10}
-
-T-PollRetransmit ::= ENUMERATED {
- ms5, ms10, ms15, ms20, ms25, ms30, ms35,
- ms40, ms45, ms50, ms55, ms60, ms65, ms70,
- ms75, ms80, ms85, ms90, ms95, ms100, ms105,
- ms110, ms115, ms120, ms125, ms130, ms135,
- ms140, ms145, ms150, ms155, ms160, ms165,
- ms170, ms175, ms180, ms185, ms190, ms195,
- ms200, ms205, ms210, ms215, ms220, ms225,
- ms230, ms235, ms240, ms245, ms250, ms300,
- ms350, ms400, ms450, ms500, spare9, spare8,
- spare7, spare6, spare5, spare4, spare3,
- spare2, spare1}
-
-PollPDU ::= ENUMERATED {
- p4, p8, p16, p32, p64, p128, p256, pInfinity}
-
-PollByte ::= ENUMERATED {
- kB25, kB50, kB75, kB100, kB125, kB250, kB375,
- kB500, kB750, kB1000, kB1250, kB1500, kB2000,
- kB3000, kBinfinity, spare1}
-
-T-Reordering ::= ENUMERATED {
- ms0, ms5, ms10, ms15, ms20, ms25, ms30, ms35,
- ms40, ms45, ms50, ms55, ms60, ms65, ms70,
- ms75, ms80, ms85, ms90, ms95, ms100, ms110,
- ms120, ms130, ms140, ms150, ms160, ms170,
- ms180, ms190, ms200, spare1}
-
-T-StatusProhibit ::= ENUMERATED {
- ms0, ms5, ms10, ms15, ms20, ms25, ms30, ms35,
- ms40, ms45, ms50, ms55, ms60, ms65, ms70,
- ms75, ms80, ms85, ms90, ms95, ms100, ms105,
- ms110, ms115, ms120, ms125, ms130, ms135,
- ms140, ms145, ms150, ms155, ms160, ms165,
- ms170, ms175, ms180, ms185, ms190, ms195,
- ms200, ms205, ms210, ms215, ms220, ms225,
- ms230, ms235, ms240, ms245, ms250, ms300,
- ms350, ms400, ms450, ms500, spare8, spare7,
- spare6, spare5, spare4, spare3, spare2,
- spare1}
-
-
-SchedulingRequestConfig ::= CHOICE {
- release NULL,
- setup SEQUENCE {
- sr-PUCCH-ResourceIndex INTEGER (0..2047),
- sr-ConfigIndex INTEGER (0..155),
- dsr-TransMax ENUMERATED {
- n4, n8, n16, n32, n64, spare3, spare2, spare1}
- }
-}
-
-
-SoundingRS-UL-ConfigCommon ::= CHOICE {
- release NULL,
- setup SEQUENCE {
- srs-BandwidthConfig ENUMERATED {bw0, bw1, bw2, bw3, bw4, bw5, bw6, bw7},
- srs-SubframeConfig ENUMERATED {
- sc0, sc1, sc2, sc3, sc4, sc5, sc6, sc7,
- sc8, sc9, sc10, sc11, sc12, sc13, sc14, sc15},
- ackNackSRS-SimultaneousTransmission BOOLEAN,
- srs-MaxUpPts ENUMERATED {true} OPTIONAL -- Cond TDD
- }
-}
-
-SoundingRS-UL-ConfigDedicated ::= CHOICE{
- release NULL,
- setup SEQUENCE {
- srs-Bandwidth ENUMERATED {bw0, bw1, bw2, bw3},
- srs-HoppingBandwidth ENUMERATED {hbw0, hbw1, hbw2, hbw3},
- freqDomainPosition INTEGER (0..23),
- duration BOOLEAN,
- srs-ConfigIndex INTEGER (0..1023),
- transmissionComb INTEGER (0..1),
- cyclicShift ENUMERATED {cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7}
- }
-}
-
-
-
-SPS-Config ::= SEQUENCE {
- semiPersistSchedC-RNTI C-RNTI OPTIONAL, -- Need OR
- sps-ConfigDL SPS-ConfigDL OPTIONAL, -- Need ON
- sps-ConfigUL SPS-ConfigUL OPTIONAL -- Need ON
-}
-
-SPS-ConfigDL ::= CHOICE{
- release NULL,
- setup SEQUENCE {
- semiPersistSchedIntervalDL ENUMERATED {
- sf10, sf20, sf32, sf40, sf64, sf80,
- sf128, sf160, sf320, sf640, spare6,
- spare5, spare4, spare3, spare2,
- spare1},
- numberOfConfSPS-Processes INTEGER (1..8),
- n1-PUCCH-AN-PersistentList N1-PUCCH-AN-PersistentList,
- ...
- }
-}
-
-SPS-ConfigUL ::= CHOICE {
- release NULL,
- setup SEQUENCE {
- semiPersistSchedIntervalUL ENUMERATED {
- sf10, sf20, sf32, sf40, sf64, sf80,
- sf128, sf160, sf320, sf640, spare6,
- spare5, spare4, spare3, spare2,
- spare1},
- implicitReleaseAfter ENUMERATED {e2, e3, e4, e8},
- p0-Persistent SEQUENCE {
- p0-NominalPUSCH-Persistent INTEGER (-126..24),
- p0-UE-PUSCH-Persistent INTEGER (-8..7)
- } OPTIONAL, -- Need OP
- twoIntervalsConfig ENUMERATED {true} OPTIONAL, -- Cond TDD
- ...
- }
-}
-
-N1-PUCCH-AN-PersistentList ::= SEQUENCE (SIZE (1..4)) OF INTEGER (0..2047)
-
-
-TDD-Config ::= SEQUENCE {
- subframeAssignment ENUMERATED {
- sa0, sa1, sa2, sa3, sa4, sa5, sa6},
- specialSubframePatterns ENUMERATED {
- ssp0, ssp1, ssp2, ssp3, ssp4,ssp5, ssp6, ssp7,
- ssp8}
-}
-
-
-TimeAlignmentTimer ::= ENUMERATED {
- sf500, sf750, sf1280, sf1920, sf2560, sf5120,
- sf10240, infinity}
-
-TPC-PDCCH-Config::= CHOICE {
- release NULL,
- setup SEQUENCE {
- tpc-RNTI BIT STRING (SIZE (16)),
- tpc-Index TPC-Index
- }
-}
-
-TPC-Index ::= CHOICE {
- indexOfFormat3 INTEGER (1..15),
- indexOfFormat3A INTEGER (1..31)
-}
-
-
-UplinkPowerControlCommon ::= SEQUENCE {
- p0-NominalPUSCH INTEGER (-126..24),
- alpha ENUMERATED {al0, al04, al05, al06, al07, al08, al09, al1},
- p0-NominalPUCCH INTEGER (-127..-96),
- deltaFList-PUCCH DeltaFList-PUCCH,
- deltaPreambleMsg3 INTEGER (-1..6)
-}
-
-UplinkPowerControlDedicated ::= SEQUENCE {
- p0-UE-PUSCH INTEGER (-8..7),
- deltaMCS-Enabled ENUMERATED {en0, en1},
- accumulationEnabled BOOLEAN,
- p0-UE-PUCCH INTEGER (-8..7),
- pSRS-Offset INTEGER (0..15),
- filterCoefficient FilterCoefficient DEFAULT fc4
-}
-
-DeltaFList-PUCCH ::= SEQUENCE {
- deltaF-PUCCH-Format1 ENUMERATED {deltaF-2, deltaF0, deltaF2},
- deltaF-PUCCH-Format1b ENUMERATED {deltaF1, deltaF3, deltaF5},
- deltaF-PUCCH-Format2 ENUMERATED {deltaF-2, deltaF0, deltaF1, deltaF2},
- deltaF-PUCCH-Format2a ENUMERATED {deltaF-2, deltaF0, deltaF2},
- deltaF-PUCCH-Format2b ENUMERATED {deltaF-2, deltaF0, deltaF2}
-}
-
-
-NextHopChainingCount ::= INTEGER (0..7)
-
-
-SecurityAlgorithmConfig ::= SEQUENCE {
- cipheringAlgorithm ENUMERATED {
- eea0, eea1, eea2, spare5, spare4, spare3,
- spare2, spare1, ...},
- integrityProtAlgorithm ENUMERATED {
- reserved, eia1, eia2, spare5, spare4, spare3,
- spare2, spare1, ...}
-}
-
-
-ShortMAC-I ::= BIT STRING (SIZE (16))
-
-
-AdditionalSpectrumEmission ::= INTEGER (1..32)
-
-
-ARFCN-ValueCDMA2000 ::= INTEGER (0..2047)
-
-
-ARFCN-ValueEUTRA ::= INTEGER (0..maxEARFCN)
-
-
-ARFCN-ValueGERAN ::= INTEGER (0..1023)
-
-
-ARFCN-ValueUTRA ::= INTEGER (0..16383)
-
-
-BandclassCDMA2000 ::= ENUMERATED {
- bc0, bc1, bc2, bc3, bc4, bc5, bc6, bc7, bc8,
- bc9, bc10, bc11, bc12, bc13, bc14, bc15, bc16,
- bc17, spare14, spare13, spare12, spare11, spare10,
- spare9, spare8, spare7, spare6, spare5, spare4,
- spare3, spare2, spare1, ...}
-
-
-BandIndicatorGERAN ::= ENUMERATED {dcs1800, pcs1900}
-
-
-CarrierFreqCDMA2000 ::= SEQUENCE {
- bandClass BandclassCDMA2000,
- arfcn ARFCN-ValueCDMA2000
-}
-
-
-CarrierFreqGERAN ::= SEQUENCE {
- arfcn ARFCN-ValueGERAN,
- bandIndicator BandIndicatorGERAN
-}
-
-
-CarrierFreqsGERAN ::= SEQUENCE {
- startingARFCN ARFCN-ValueGERAN,
- bandIndicator BandIndicatorGERAN,
- followingARFCNs CHOICE {
- explicitListOfARFCNs ExplicitListOfARFCNs,
- equallySpacedARFCNs SEQUENCE {
- arfcn-Spacing INTEGER (1..8),
- numberOfFollowingARFCNs INTEGER (0..31)
- },
- variableBitMapOfARFCNs OCTET STRING (SIZE (1..16))
- }
-}
-
-ExplicitListOfARFCNs ::= SEQUENCE (SIZE (0..31)) OF ARFCN-ValueGERAN
-
-
-CDMA2000-Type ::= ENUMERATED {type1XRTT, typeHRPD}
-
-
-CellIdentity ::= BIT STRING (SIZE (28))
-
-
-CellIndexList ::= SEQUENCE (SIZE (1..maxCellMeas)) OF CellIndex
-
-CellIndex ::= INTEGER (1..maxCellMeas)
-
-
-CellReselectionPriority ::= INTEGER (0..7)
-
-
-CSFB-RegistrationParam1XRTT ::= SEQUENCE {
- sid BIT STRING (SIZE (15)),
- nid BIT STRING (SIZE (16)),
- multipleSID BOOLEAN,
- multipleNID BOOLEAN,
- homeReg BOOLEAN,
- foreignSIDReg BOOLEAN,
- foreignNIDReg BOOLEAN,
- parameterReg BOOLEAN,
- powerUpReg BOOLEAN,
- registrationPeriod BIT STRING (SIZE (7)),
- registrationZone BIT STRING (SIZE (12)),
- totalZone BIT STRING (SIZE (3)),
- zoneTimer BIT STRING (SIZE (3))
-}
-
-
-CellGlobalIdEUTRA ::= SEQUENCE {
- plmn-Identity PLMN-Identity,
- cellIdentity CellIdentity
-}
-
-
-CellGlobalIdUTRA ::= SEQUENCE {
- plmn-Identity PLMN-Identity,
- cellIdentity BIT STRING (SIZE (28))
-}
-
-
-CellGlobalIdGERAN ::= SEQUENCE {
- plmn-Identity PLMN-Identity,
- locationAreaCode BIT STRING (SIZE (16)),
- cellIdentity BIT STRING (SIZE (16))
-}
-
-
-CellGlobalIdCDMA2000 ::= CHOICE {
- cellGlobalId1XRTT BIT STRING (SIZE (47)),
- cellGlobalIdHRPD BIT STRING (SIZE (128))
-}
-
-
-MobilityControlInfo ::= SEQUENCE {
- targetPhysCellId PhysCellId,
- carrierFreq CarrierFreqEUTRA OPTIONAL, -- Cond HO-toEUTRA
- carrierBandwidth CarrierBandwidthEUTRA OPTIONAL, -- Cond HO-toEUTRA
- additionalSpectrumEmission AdditionalSpectrumEmission OPTIONAL, -- Cond HO-toEUTRA
- t304 ENUMERATED {
- ms50, ms100, ms150, ms200, ms500, ms1000,
- ms2000, spare1},
- newUE-Identity C-RNTI,
- radioResourceConfigCommon RadioResourceConfigCommon,
- rach-ConfigDedicated RACH-ConfigDedicated OPTIONAL, -- Need OP
- ...
-}
-
-CarrierBandwidthEUTRA ::= SEQUENCE {
- dl-Bandwidth ENUMERATED {
- n6, n15, n25, n50, n75, n100, spare10,
- spare9, spare8, spare7, spare6, spare5,
- spare4, spare3, spare2, spare1},
- ul-Bandwidth ENUMERATED {
- n6, n15, n25, n50, n75, n100, spare10,
- spare9, spare8, spare7, spare6, spare5,
- spare4, spare3, spare2, spare1} OPTIONAL -- Need OP
-}
-
-CarrierFreqEUTRA ::= SEQUENCE {
- dl-CarrierFreq ARFCN-ValueEUTRA,
- ul-CarrierFreq ARFCN-ValueEUTRA OPTIONAL -- Cond FDD
-}
-
-
-MobilityParametersCDMA2000 ::= OCTET STRING
-
-
-MobilityStateParameters ::= SEQUENCE {
- t-Evaluation ENUMERATED {
- s30, s60, s120, s180, s240, spare3, spare2, spare1},
- t-HystNormal ENUMERATED {
- s30, s60, s120, s180, s240, spare3, spare2, spare1},
- n-CellChangeMedium INTEGER (1..16),
- n-CellChangeHigh INTEGER (1..16)
-}
-
-
-PhysCellId ::= INTEGER (0..503)
-
-
-PhysCellIdRange ::= SEQUENCE {
- start PhysCellId,
- range ENUMERATED {
- n4, n8, n12, n16, n24, n32, n48, n64, n84,
- n96, n128, n168, n252, n504, spare2,
- spare1} OPTIONAL -- Need OP
-}
-
-
-PhysCellIdCDMA2000 ::= INTEGER (0..maxPNOffset)
-
-
-PhysCellIdGERAN ::= SEQUENCE {
- networkColourCode BIT STRING (SIZE (3)),
- baseStationColourCode BIT STRING (SIZE (3))
-}
-
-
-PhysCellIdUTRA-FDD ::= INTEGER (0..511)
-
-
-PhysCellIdUTRA-TDD ::= INTEGER (0..127)
-
-
-PLMN-Identity ::= SEQUENCE {
- mcc MCC OPTIONAL, -- Cond MCC
- mnc MNC
-}
-
-MCC ::= SEQUENCE (SIZE (3)) OF
- MCC-MNC-Digit
-
-MNC ::= SEQUENCE (SIZE (2..3)) OF
- MCC-MNC-Digit
-
-MCC-MNC-Digit ::= INTEGER (0..9)
-
-
-
-PreRegistrationInfoHRPD ::= SEQUENCE {
- preRegistrationAllowed BOOLEAN,
- preRegistrationZoneId PreRegistrationZoneIdHRPD OPTIONAL, -- cond PreRegAllowed
- secondaryPreRegistrationZoneIdList SecondaryPreRegistrationZoneIdListHRPD OPTIONAL -- Need OR
-}
-
-SecondaryPreRegistrationZoneIdListHRPD ::= SEQUENCE (SIZE (1..2)) OF PreRegistrationZoneIdHRPD
-
-PreRegistrationZoneIdHRPD ::= INTEGER (0..255)
-
-
-Q-RxLevMin ::= INTEGER (-70..-22)
-
-
-Q-OffsetRange ::= ENUMERATED {
- dB-24, dB-22, dB-20, dB-18, dB-16, dB-14,
- dB-12, dB-10, dB-8, dB-6, dB-5, dB-4, dB-3,
- dB-2, dB-1, dB0, dB1, dB2, dB3, dB4, dB5,
- dB6, dB8, dB10, dB12, dB14, dB16, dB18,
- dB20, dB22, dB24}
-
-
-Q-OffsetRangeInterRAT ::= INTEGER (-15..15)
-
-
-ReselectionThreshold ::= INTEGER (0..31)
-
-
-SpeedStateScaleFactors ::= SEQUENCE {
- sf-Medium ENUMERATED {oDot25, oDot5, oDot75, lDot0},
- sf-High ENUMERATED {oDot25, oDot5, oDot75, lDot0}
-}
-
-SystemTimeInfoCDMA2000 ::= SEQUENCE {
- cdma-EUTRA-Synchronisation BOOLEAN,
- cdma-SystemTime CHOICE {
- synchronousSystemTime BIT STRING (SIZE (39)),
- asynchronousSystemTime BIT STRING (SIZE (49))
- }
-}
-
-
-TrackingAreaCode ::= BIT STRING (SIZE (16))
-
-
-T-Reselection ::= INTEGER (0..7)
-
-
-AllowedMeasBandwidth ::= ENUMERATED {mbw6, mbw15, mbw25, mbw50, mbw75, mbw100}
-
-
-Hysteresis ::= INTEGER (0..30)
-
-
-MeasConfig ::= SEQUENCE {
- -- Measurement objects
- measObjectToRemoveList MeasObjectToRemoveList OPTIONAL, -- Need ON
- measObjectToAddModList MeasObjectToAddModList OPTIONAL, -- Need ON
- -- Reporting configurations
- reportConfigToRemoveList ReportConfigToRemoveList OPTIONAL, -- Need ON
- reportConfigToAddModList ReportConfigToAddModList OPTIONAL, -- Need ON
- -- Measurement identities
- measIdToRemoveList MeasIdToRemoveList OPTIONAL, -- Need ON
- measIdToAddModList MeasIdToAddModList OPTIONAL, -- Need ON
- -- Other parameters
- quantityConfig QuantityConfig OPTIONAL, -- Need ON
- measGapConfig MeasGapConfig OPTIONAL, -- Need ON
- s-Measure RSRP-Range OPTIONAL, -- Need ON
- preRegistrationInfoHRPD PreRegistrationInfoHRPD OPTIONAL, -- Need OP
- speedStatePars CHOICE {
- release NULL,
- setup SEQUENCE {
- mobilityStateParameters MobilityStateParameters,
- timeToTrigger-SF SpeedStateScaleFactors
- }
- } OPTIONAL, -- Need ON
- ...
-}
-
-MeasIdToRemoveList ::= SEQUENCE (SIZE (1..maxMeasId)) OF MeasId
-
-MeasObjectToRemoveList ::= SEQUENCE (SIZE (1..maxObjectId)) OF MeasObjectId
-
-ReportConfigToRemoveList ::= SEQUENCE (SIZE (1..maxReportConfigId)) OF ReportConfigId
-
-
-MeasGapConfig ::= CHOICE {
- release NULL,
- setup SEQUENCE {
- gapOffset CHOICE {
- gp0 INTEGER (0..39),
- gp1 INTEGER (0..79),
- ...
- }
- }
-}
-
-
-MeasId ::= INTEGER (1..maxMeasId)
-
-
-MeasIdToAddModList ::= SEQUENCE (SIZE (1..maxMeasId)) OF MeasIdToAddMod
-
-MeasIdToAddMod ::= SEQUENCE {
- measId MeasId,
- measObjectId MeasObjectId,
- reportConfigId ReportConfigId
-}
-
-
-MeasObjectCDMA2000 ::= SEQUENCE {
- cdma2000-Type CDMA2000-Type,
- carrierFreq CarrierFreqCDMA2000,
- searchWindowSize INTEGER (0..15) OPTIONAL, -- Need ON
- offsetFreq Q-OffsetRangeInterRAT DEFAULT 0,
- cellsToRemoveList CellIndexList OPTIONAL, -- Need ON
- cellsToAddModList CellsToAddModListCDMA2000 OPTIONAL, -- Need ON
- cellForWhichToReportCGI PhysCellIdCDMA2000 OPTIONAL, -- Need ON
- ...
-}
-
-CellsToAddModListCDMA2000 ::= SEQUENCE (SIZE (1..maxCellMeas)) OF CellsToAddModCDMA2000
-
-CellsToAddModCDMA2000 ::= SEQUENCE {
- cellIndex INTEGER (1..maxCellMeas),
- physCellId PhysCellIdCDMA2000
-}
-
-
-MeasObjectEUTRA ::= SEQUENCE {
- carrierFreq ARFCN-ValueEUTRA,
- allowedMeasBandwidth AllowedMeasBandwidth,
- presenceAntennaPort1 PresenceAntennaPort1,
- neighCellConfig NeighCellConfig,
- offsetFreq Q-OffsetRange DEFAULT dB0,
- -- Neighbour cell list
- cellsToRemoveList CellIndexList OPTIONAL, -- Need ON
- cellsToAddModList CellsToAddModList OPTIONAL, -- Need ON
- -- Black list
- blackCellsToRemoveList CellIndexList OPTIONAL, -- Need ON
- blackCellsToAddModList BlackCellsToAddModList OPTIONAL, -- Need ON
- cellForWhichToReportCGI PhysCellId OPTIONAL, -- Need ON
- ...
-}
-
-CellsToAddModList ::= SEQUENCE (SIZE (1..maxCellMeas)) OF CellsToAddMod
-
-CellsToAddMod ::= SEQUENCE {
- cellIndex INTEGER (1..maxCellMeas),
- physCellId PhysCellId,
- cellIndividualOffset Q-OffsetRange
-}
-
-BlackCellsToAddModList ::= SEQUENCE (SIZE (1..maxCellMeas)) OF BlackCellsToAddMod
-
-BlackCellsToAddMod ::= SEQUENCE {
- cellIndex INTEGER (1..maxCellMeas),
- physCellIdRange PhysCellIdRange
-}
-
-
-MeasObjectGERAN ::= SEQUENCE {
- carrierFreqs CarrierFreqsGERAN,
- offsetFreq Q-OffsetRangeInterRAT DEFAULT 0,
- ncc-Permitted BIT STRING(SIZE (8)) DEFAULT '11111111'B,
- cellForWhichToReportCGI PhysCellIdGERAN OPTIONAL, -- Need ON
- ...
-}
-
-
-MeasObjectId ::= INTEGER (1..maxObjectId)
-
-
-MeasObjectToAddModList ::= SEQUENCE (SIZE (1..maxObjectId)) OF MeasObjectToAddMod
-
-MeasObjectToAddMod ::= SEQUENCE {
- measObjectId MeasObjectId,
- measObject CHOICE {
- measObjectEUTRA MeasObjectEUTRA,
- measObjectUTRA MeasObjectUTRA,
- measObjectGERAN MeasObjectGERAN,
- measObjectCDMA2000 MeasObjectCDMA2000,
- ...
- }
-}
-
-
-MeasObjectUTRA ::= SEQUENCE {
- carrierFreq ARFCN-ValueUTRA,
- offsetFreq Q-OffsetRangeInterRAT DEFAULT 0,
- cellsToRemoveList CellIndexList OPTIONAL, -- Need ON
- cellsToAddModList CHOICE {
- cellsToAddModListUTRA-FDD CellsToAddModListUTRA-FDD,
- cellsToAddModListUTRA-TDD CellsToAddModListUTRA-TDD
- } OPTIONAL, -- Need ON
- cellForWhichToReportCGI CHOICE {
- utra-FDD PhysCellIdUTRA-FDD,
- utra-TDD PhysCellIdUTRA-TDD
- } OPTIONAL, -- Need ON
- ...
-}
-
-CellsToAddModListUTRA-FDD ::= SEQUENCE (SIZE (1..maxCellMeas)) OF CellsToAddModUTRA-FDD
-
-CellsToAddModUTRA-FDD ::= SEQUENCE {
- cellIndex INTEGER (1..maxCellMeas),
- physCellId PhysCellIdUTRA-FDD
-}
-
-CellsToAddModListUTRA-TDD ::= SEQUENCE (SIZE (1..maxCellMeas)) OF CellsToAddModUTRA-TDD
-
-CellsToAddModUTRA-TDD ::= SEQUENCE {
- cellIndex INTEGER (1..maxCellMeas),
- physCellId PhysCellIdUTRA-TDD
-}
-
-
-MeasResults ::= SEQUENCE {
- measId MeasId,
- measResultServCell SEQUENCE {
- rsrpResult RSRP-Range,
- rsrqResult RSRQ-Range
- },
- measResultNeighCells CHOICE {
- measResultListEUTRA MeasResultListEUTRA,
- measResultListUTRA MeasResultListUTRA,
- measResultListGERAN MeasResultListGERAN,
- measResultsCDMA2000 MeasResultsCDMA2000,
- ...
- } OPTIONAL,
- ...
-}
-
-MeasResultListEUTRA ::= SEQUENCE (SIZE (1..maxCellReport)) OF MeasResultEUTRA
-
-MeasResultEUTRA ::= SEQUENCE {
- physCellId PhysCellId,
- cgi-Info SEQUENCE {
- cellGlobalId CellGlobalIdEUTRA,
- trackingAreaCode TrackingAreaCode,
- plmn-IdentityList PLMN-IdentityList2 OPTIONAL
- } OPTIONAL,
- measResult SEQUENCE {
- rsrpResult RSRP-Range OPTIONAL,
- rsrqResult RSRQ-Range OPTIONAL,
- ...
- }
-}
-
-MeasResultListUTRA ::= SEQUENCE (SIZE (1..maxCellReport)) OF MeasResultUTRA
-
-MeasResultUTRA ::= SEQUENCE {
- physCellId CHOICE {
- fdd PhysCellIdUTRA-FDD,
- tdd PhysCellIdUTRA-TDD
- },
- cgi-Info SEQUENCE {
- cellGlobalId CellGlobalIdUTRA,
- locationAreaCode BIT STRING (SIZE (16)) OPTIONAL,
- routingAreaCode BIT STRING (SIZE (8)) OPTIONAL,
- plmn-IdentityList PLMN-IdentityList2 OPTIONAL
- } OPTIONAL,
- measResult SEQUENCE {
- utra-RSCP INTEGER (-5..91) OPTIONAL,
- utra-EcN0 INTEGER (0..49) OPTIONAL,
- ...
- }
-}
-
-MeasResultListGERAN ::= SEQUENCE (SIZE (1..maxCellReport)) OF MeasResultGERAN
-
-MeasResultGERAN ::= SEQUENCE {
- carrierFreq CarrierFreqGERAN,
- physCellId PhysCellIdGERAN,
- cgi-Info SEQUENCE {
- cellGlobalId CellGlobalIdGERAN,
- routingAreaCode BIT STRING (SIZE (8)) OPTIONAL
- } OPTIONAL,
- measResult SEQUENCE {
- rssi INTEGER (0..63),
- ...
- }
-}
-
-MeasResultsCDMA2000 ::= SEQUENCE {
- preRegistrationStatusHRPD BOOLEAN,
- measResultListCDMA2000 MeasResultListCDMA2000
-}
-
-MeasResultListCDMA2000 ::= SEQUENCE (SIZE (1..maxCellReport)) OF MeasResultCDMA2000
-
-MeasResultCDMA2000 ::= SEQUENCE {
- physCellId PhysCellIdCDMA2000,
- cgi-Info CellGlobalIdCDMA2000 OPTIONAL,
- measResult SEQUENCE {
- pilotPnPhase INTEGER (0..32767) OPTIONAL,
- pilotStrength INTEGER (0..63),
- ...
- }
-}
-
-PLMN-IdentityList2 ::= SEQUENCE (SIZE (1..5)) OF PLMN-Identity
-
-
-QuantityConfig ::= SEQUENCE {
- quantityConfigEUTRA QuantityConfigEUTRA OPTIONAL, -- Need ON
- quantityConfigUTRA QuantityConfigUTRA OPTIONAL, -- Need ON
- quantityConfigGERAN QuantityConfigGERAN OPTIONAL, -- Need ON
- quantityConfigCDMA2000 QuantityConfigCDMA2000 OPTIONAL, -- Need ON
- ...
-}
-
-QuantityConfigEUTRA ::= SEQUENCE {
- filterCoefficientRSRP FilterCoefficient DEFAULT fc4,
- filterCoefficientRSRQ FilterCoefficient DEFAULT fc4
-}
-
-QuantityConfigUTRA ::= SEQUENCE {
- measQuantityUTRA-FDD ENUMERATED {cpich-RSCP, cpich-EcN0},
- measQuantityUTRA-TDD ENUMERATED {pccpch-RSCP},
- filterCoefficient FilterCoefficient DEFAULT fc4
-}
-
-QuantityConfigGERAN ::= SEQUENCE {
- measQuantityGERAN ENUMERATED {rssi},
- filterCoefficient FilterCoefficient DEFAULT fc2
-}
-
-QuantityConfigCDMA2000 ::= SEQUENCE {
- measQuantityCDMA2000 ENUMERATED {pilotStrength, pilotPnPhaseAndPilotStrength}
-}
-
-
-ReportConfigEUTRA ::= SEQUENCE {
- triggerType CHOICE {
- event SEQUENCE {
- eventId CHOICE {
- eventA1 SEQUENCE {
- a1-Threshold ThresholdEUTRA
- },
- eventA2 SEQUENCE {
- a2-Threshold ThresholdEUTRA
- },
- eventA3 SEQUENCE {
- a3-Offset INTEGER (-30..30),
- reportOnLeave BOOLEAN
- },
- eventA4 SEQUENCE {
- a4-Threshold ThresholdEUTRA
- },
- eventA5 SEQUENCE {
- a5-Threshold1 ThresholdEUTRA,
- a5-Threshold2 ThresholdEUTRA
- },
- ...
- },
- hysteresis Hysteresis,
- timeToTrigger TimeToTrigger
- },
- periodical SEQUENCE {
- purpose ENUMERATED {
- reportStrongestCells, reportCGI}
- }
- },
- triggerQuantity ENUMERATED {rsrp, rsrq},
- reportQuantity ENUMERATED {sameAsTriggerQuantity, both},
- maxReportCells INTEGER (1..maxCellReport),
- reportInterval ReportInterval,
- reportAmount ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity},
- ...
-}
-
-ThresholdEUTRA ::= CHOICE{
- threshold-RSRP RSRP-Range,
- threshold-RSRQ RSRQ-Range
-}
-
-
-ReportConfigId ::= INTEGER (1..maxReportConfigId)
-
-
-ReportConfigInterRAT ::= SEQUENCE {
- triggerType CHOICE {
- event SEQUENCE {
- eventId CHOICE {
- eventB1 SEQUENCE {
- b1-Threshold CHOICE {
- b1-ThresholdUTRA ThresholdUTRA,
- b1-ThresholdGERAN ThresholdGERAN,
- b1-ThresholdCDMA2000 ThresholdCDMA2000
- }
- },
- eventB2 SEQUENCE {
- b2-Threshold1 ThresholdEUTRA,
- b2-Threshold2 CHOICE {
- b2-Threshold2UTRA ThresholdUTRA,
- b2-Threshold2GERAN ThresholdGERAN,
- b2-Threshold2CDMA2000 ThresholdCDMA2000
- }
- },
- ...
- },
- hysteresis Hysteresis,
- timeToTrigger TimeToTrigger
- },
- periodical SEQUENCE {
- purpose ENUMERATED {
- reportStrongestCells,
- reportStrongestCellsForSON,
- reportCGI}
- }
- },
- maxReportCells INTEGER (1..maxCellReport),
- reportInterval ReportInterval,
- reportAmount ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity},
- ...
-}
-
-ThresholdUTRA ::= CHOICE{
- utra-RSCP INTEGER (-5..91),
- utra-EcN0 INTEGER (0..49)
-}
-
-ThresholdGERAN ::= INTEGER (0..63)
-
-ThresholdCDMA2000 ::= INTEGER (0..63)
-
-
-ReportConfigToAddModList ::= SEQUENCE (SIZE (1..maxReportConfigId)) OF ReportConfigToAddMod
-
-ReportConfigToAddMod ::= SEQUENCE {
- reportConfigId ReportConfigId,
- reportConfig CHOICE {
- reportConfigEUTRA ReportConfigEUTRA,
- reportConfigInterRAT ReportConfigInterRAT
- }
-}
-
-
-
-ReportInterval ::= ENUMERATED {
- ms120, ms240, ms480, ms640, ms1024, ms2048, ms5120, ms10240,
- min1, min6, min12, min30, min60, spare3, spare2, spare1}
-
-
-RSRP-Range ::= INTEGER(0..97)
-
-
-RSRQ-Range ::= INTEGER(0..34)
-
-
-TimeToTrigger ::= ENUMERATED {
- ms0, ms40, ms64, ms80, ms100, ms128, ms160, ms256,
- ms320, ms480, ms512, ms640, ms1024, ms1280, ms2560,
- ms5120}
-
-
-C-RNTI ::= BIT STRING (SIZE (16))
-
-
-DedicatedInfoCDMA2000 ::= OCTET STRING
-
-
-DedicatedInfoNAS ::= OCTET STRING
-
-
-FilterCoefficient ::= ENUMERATED {
- fc0, fc1, fc2, fc3, fc4, fc5,
- fc6, fc7, fc8, fc9, fc11, fc13,
- fc15, fc17, fc19, spare1, ...}
-
-
-MMEC ::= BIT STRING (SIZE (8))
-
-
-NeighCellConfig ::= BIT STRING (SIZE (2))
-
-
-RAND-CDMA2000 ::= BIT STRING (SIZE (32))
-
-
-RAT-Type ::= ENUMERATED {
- eutra, utra, geran-cs, geran-ps, cdma2000-1XRTT,
- spare3, spare2, spare1, ...}
-
-
-RRC-TransactionIdentifier ::= INTEGER (0..3)
-
-
-S-TMSI ::= SEQUENCE {
- mmec MMEC,
- m-TMSI BIT STRING (SIZE (32))
-}
-
-
-UE-CapabilityRAT-ContainerList ::=SEQUENCE (SIZE (0..maxRAT-Capabilities)) OF UE-CapabilityRAT-Container
-
-UE-CapabilityRAT-Container ::= SEQUENCE {
- rat-Type RAT-Type,
- ueCapabilityRAT-Container OCTET STRING
-}
-
-
-UE-EUTRA-Capability ::= SEQUENCE {
- accessStratumRelease AccessStratumRelease,
- ue-Category INTEGER (1..5),
- pdcp-Parameters PDCP-Parameters,
- phyLayerParameters PhyLayerParameters,
- rf-Parameters RF-Parameters,
- measParameters MeasParameters,
- featureGroupIndicators BIT STRING (SIZE (32)) OPTIONAL,
- interRAT-Parameters SEQUENCE {
- utraFDD IRAT-ParametersUTRA-FDD OPTIONAL,
- utraTDD128 IRAT-ParametersUTRA-TDD128 OPTIONAL,
- utraTDD384 IRAT-ParametersUTRA-TDD384 OPTIONAL,
- utraTDD768 IRAT-ParametersUTRA-TDD768 OPTIONAL,
- geran IRAT-ParametersGERAN OPTIONAL,
- cdma2000-HRPD IRAT-ParametersCDMA2000-HRPD OPTIONAL,
- cdma2000-1xRTT IRAT-ParametersCDMA2000-1XRTT OPTIONAL
- },
- nonCriticalExtension SEQUENCE {} OPTIONAL
-}
-
-AccessStratumRelease ::= ENUMERATED {
- rel8, spare7, spare6, spare5, spare4, spare3,
- spare2, spare1, ...}
-
-PDCP-Parameters ::= SEQUENCE {
- supportedROHC-Profiles SEQUENCE {
- profile0x0001 BOOLEAN,
- profile0x0002 BOOLEAN,
- profile0x0003 BOOLEAN,
- profile0x0004 BOOLEAN,
- profile0x0006 BOOLEAN,
- profile0x0101 BOOLEAN,
- profile0x0102 BOOLEAN,
- profile0x0103 BOOLEAN,
- profile0x0104 BOOLEAN
- },
- maxNumberROHC-ContextSessions ENUMERATED {
- cs2, cs4, cs8, cs12, cs16, cs24, cs32,
- cs48, cs64, cs128, cs256, cs512, cs1024,
- cs16384, spare2, spare1} DEFAULT cs16,
- ...
-}
-
-PhyLayerParameters ::= SEQUENCE {
- ue-TxAntennaSelectionSupported BOOLEAN,
- ue-SpecificRefSigsSupported BOOLEAN
-}
-
-RF-Parameters ::= SEQUENCE {
- supportedBandListEUTRA SupportedBandListEUTRA
-}
-
-SupportedBandListEUTRA ::= SEQUENCE (SIZE (1..maxBands)) OF SupportedBandEUTRA
-
-SupportedBandEUTRA ::= SEQUENCE {
- bandEUTRA INTEGER (1..64),
- halfDuplex BOOLEAN
-}
-
-MeasParameters ::= SEQUENCE {
- bandListEUTRA BandListEUTRA
-}
-
-BandListEUTRA ::= SEQUENCE (SIZE (1..maxBands)) OF BandInfoEUTRA
-
-BandInfoEUTRA ::= SEQUENCE {
- interFreqBandList InterFreqBandList,
- interRAT-BandList InterRAT-BandList OPTIONAL
-}
-
-InterFreqBandList ::= SEQUENCE (SIZE (1..maxBands)) OF InterFreqBandInfo
-
-InterFreqBandInfo ::= SEQUENCE {
- interFreqNeedForGaps BOOLEAN
-}
-
-InterRAT-BandList ::= SEQUENCE (SIZE (1..maxBands)) OF InterRAT-BandInfo
-
-InterRAT-BandInfo ::= SEQUENCE {
- interRAT-NeedForGaps BOOLEAN
-}
-
-IRAT-ParametersUTRA-FDD ::= SEQUENCE {
- supportedBandListUTRA-FDD SupportedBandListUTRA-FDD
-}
-
-SupportedBandListUTRA-FDD ::= SEQUENCE (SIZE (1..maxBands)) OF SupportedBandUTRA-FDD
-
-SupportedBandUTRA-FDD ::= ENUMERATED {
- bandI, bandII, bandIII, bandIV, bandV, bandVI,
- bandVII, bandVIII, bandIX, bandX, bandXI,
- bandXII, bandXIII, bandXIV, bandXV, bandXVI, ...}
-
-IRAT-ParametersUTRA-TDD128 ::= SEQUENCE {
- supportedBandListUTRA-TDD128 SupportedBandListUTRA-TDD128
-}
-
-SupportedBandListUTRA-TDD128 ::= SEQUENCE (SIZE (1..maxBands)) OF SupportedBandUTRA-TDD128
-
-SupportedBandUTRA-TDD128 ::= ENUMERATED {
- a, b, c, d, e, f, g, h, i, j, k, l, m, n,
- o, p, ...}
-
-IRAT-ParametersUTRA-TDD384 ::= SEQUENCE {
- supportedBandListUTRA-TDD384 SupportedBandListUTRA-TDD384
-}
-
-SupportedBandListUTRA-TDD384 ::= SEQUENCE (SIZE (1..maxBands)) OF SupportedBandUTRA-TDD384
-
-SupportedBandUTRA-TDD384 ::= ENUMERATED {
- a, b, c, d, e, f, g, h, i, j, k, l, m, n,
- o, p, ...}
-
-IRAT-ParametersUTRA-TDD768 ::= SEQUENCE {
- supportedBandListUTRA-TDD768 SupportedBandListUTRA-TDD768
-}
-
-SupportedBandListUTRA-TDD768 ::= SEQUENCE (SIZE (1..maxBands)) OF SupportedBandUTRA-TDD768
-
-SupportedBandUTRA-TDD768 ::= ENUMERATED {
- a, b, c, d, e, f, g, h, i, j, k, l, m, n,
- o, p, ...}
-
-IRAT-ParametersGERAN ::= SEQUENCE {
- supportedBandListGERAN SupportedBandListGERAN,
- interRAT-PS-HO-ToGERAN BOOLEAN
-}
-
-SupportedBandListGERAN ::= SEQUENCE (SIZE (1..maxBands)) OF SupportedBandGERAN
-
-SupportedBandGERAN ::= ENUMERATED {
- gsm450, gsm480, gsm710, gsm750, gsm810, gsm850,
- gsm900P, gsm900E, gsm900R, gsm1800, gsm1900,
- spare5, spare4, spare3, spare2, spare1, ...}
-
-IRAT-ParametersCDMA2000-HRPD ::= SEQUENCE {
- supportedBandListHRPD SupportedBandListHRPD,
- tx-ConfigHRPD ENUMERATED {single, dual},
- rx-ConfigHRPD ENUMERATED {single, dual}
-}
-
-SupportedBandListHRPD ::= SEQUENCE (SIZE (1..maxCDMA-BandClass)) OF BandclassCDMA2000
-
-IRAT-ParametersCDMA2000-1XRTT ::= SEQUENCE {
- supportedBandList1XRTT SupportedBandList1XRTT,
- tx-Config1XRTT ENUMERATED {single, dual},
- rx-Config1XRTT ENUMERATED {single, dual}
-}
-
-SupportedBandList1XRTT ::= SEQUENCE (SIZE (1..maxCDMA-BandClass)) OF BandclassCDMA2000
-
-
-UE-TimersAndConstants ::= SEQUENCE {
- t300 ENUMERATED {
- ms100, ms200, ms300, ms400, ms600, ms1000, ms1500,
- ms2000},
- t301 ENUMERATED {
- ms100, ms200, ms300, ms400, ms600, ms1000, ms1500,
- ms2000},
- t310 ENUMERATED {
- ms0, ms50, ms100, ms200, ms500, ms1000, ms2000},
- n310 ENUMERATED {
- n1, n2, n3, n4, n6, n8, n10, n20},
- t311 ENUMERATED {
- ms1000, ms3000, ms5000, ms10000, ms15000,
- ms20000, ms30000},
- n311 ENUMERATED {
- n1, n2, n3, n4, n5, n6, n8, n10},
- ...
-}
-
-
-maxBands INTEGER ::= 64 -- Maximum number of bands listed in EUTRA UE caps
-maxCDMA-BandClass INTEGER ::= 32 -- Maximum value of the CDMA band classes
-maxCellBlack INTEGER ::= 16 -- Maximum number of blacklisted cells
- -- listed in SIB type 4 and 5
-maxCellInter INTEGER ::= 16 -- Maximum number of neighbouring inter-frequency
- -- cells listed in SIB type 5
-maxCellIntra INTEGER ::= 16 -- Maximum number of neighbouring intra-frequency
- -- cells listed in SIB type 4
-maxCellMeas INTEGER ::= 32 -- Maximum number of entries in each of the neighbour
- -- cell lists in a measurement object
-maxCellReport INTEGER ::= 8 -- Maximum number of reported cells
-maxDRB INTEGER ::= 11 -- Maximum number of Data Radio Bearers
-maxEARFCN INTEGER ::= 65535 -- Maximum value of EUTRA carrier fequency
-maxFreq INTEGER ::= 8 -- Maximum number of EUTRA carrier frequencies
-maxGERAN-SI INTEGER ::= 10 -- Maximum number of GERAN SI blocks that can be
- -- provided as part of NACC information
-maxGNFG INTEGER ::= 16 -- Maximum number of GERAN neighbour freq groups
-maxMBSFN-Allocations INTEGER ::= 8 -- Maximum number of MBSFN frame allocations with
- -- different offset
-maxMCS-1 INTEGER ::= 16 -- Maximum number of PUCCH formats (MCS)
-maxMeasId INTEGER ::= 32
-maxObjectId INTEGER ::= 32
-maxPageRec INTEGER ::= 16 --
-maxPNOffset INTEGER ::= 511 -- Maximum number of CDMA2000 PNOffsets
-maxRAT-Capabilities INTEGER ::= 8 -- Maximum number of interworking RATs (incl EUTRA)
-maxReportConfigId INTEGER ::= 32
-maxSIB INTEGER ::= 32 -- Maximum number of SIBs
-maxSIB-1 INTEGER ::= 31
-maxSI-Message INTEGER ::= 32 -- Maximum number of SI messages
-maxUTRA-FDD-Carrier INTEGER ::= 16 -- Maximum number of UTRA FDD carrier frequencies
-maxUTRA-TDD-Carrier INTEGER ::= 16 -- Maximum number of UTRA TDD carrier frequencies
-
-
-END
+-- 3GPP TS 36.331 v9.2.0
+-- http://cdmweb.ericsson.se/TeamCenter/controller/ViewDocs?DocumentName=51%2F15519-10%2FFCP1039669%2F11&Revision=A
+
+EUTRA-RRC-Definitions DEFINITIONS AUTOMATIC TAGS ::=
+
+BEGIN
+
+
+BCCH-BCH-Message ::= SEQUENCE {
+ message BCCH-BCH-MessageType
+}
+
+BCCH-BCH-MessageType ::= MasterInformationBlock
+
+
+BCCH-DL-SCH-Message ::= SEQUENCE {
+ message BCCH-DL-SCH-MessageType
+}
+
+BCCH-DL-SCH-MessageType ::= CHOICE {
+ c1 CHOICE {
+ systemInformation SystemInformation,
+ systemInformationBlockType1 SystemInformationBlockType1
+ },
+ messageClassExtension SEQUENCE {}
+}
+
+
+MCCH-Message ::= SEQUENCE {
+ message MCCH-MessageType
+}
+
+MCCH-MessageType ::= CHOICE {
+ c1 CHOICE {
+ mbsfnAreaConfiguration-r9 MBSFNAreaConfiguration-r9
+ },
+ messageClassExtension SEQUENCE {}
+}
+
+
+PCCH-Message ::= SEQUENCE {
+ message PCCH-MessageType
+}
+
+PCCH-MessageType ::= CHOICE {
+ c1 CHOICE {
+ paging Paging
+ },
+ messageClassExtension SEQUENCE {}
+}
+
+
+DL-CCCH-Message ::= SEQUENCE {
+ message DL-CCCH-MessageType
+}
+
+DL-CCCH-MessageType ::= CHOICE {
+ c1 CHOICE {
+ rrcConnectionReestablishment RRCConnectionReestablishment,
+ rrcConnectionReestablishmentReject RRCConnectionReestablishmentReject,
+ rrcConnectionReject RRCConnectionReject,
+ rrcConnectionSetup RRCConnectionSetup
+ },
+ messageClassExtension SEQUENCE {}
+}
+
+
+DL-DCCH-Message ::= SEQUENCE {
+ message DL-DCCH-MessageType
+}
+
+DL-DCCH-MessageType ::= CHOICE {
+ c1 CHOICE {
+ csfbParametersResponseCDMA2000 CSFBParametersResponseCDMA2000,
+ dlInformationTransfer DLInformationTransfer,
+ handoverFromEUTRAPreparationRequest HandoverFromEUTRAPreparationRequest,
+ mobilityFromEUTRACommand MobilityFromEUTRACommand,
+ rrcConnectionReconfiguration RRCConnectionReconfiguration,
+ rrcConnectionRelease RRCConnectionRelease,
+ securityModeCommand SecurityModeCommand,
+ ueCapabilityEnquiry UECapabilityEnquiry,
+ counterCheck CounterCheck,
+ ueInformationRequest-r9 UEInformationRequest-r9,
+ spare6 NULL, spare5 NULL, spare4 NULL,
+ spare3 NULL, spare2 NULL, spare1 NULL
+ },
+ messageClassExtension SEQUENCE {}
+}
+
+
+UL-CCCH-Message ::= SEQUENCE {
+ message UL-CCCH-MessageType
+}
+
+UL-CCCH-MessageType ::= CHOICE {
+ c1 CHOICE {
+ rrcConnectionReestablishmentRequest RRCConnectionReestablishmentRequest,
+ rrcConnectionRequest RRCConnectionRequest
+ },
+ messageClassExtension SEQUENCE {}
+}
+
+
+UL-DCCH-Message ::= SEQUENCE {
+ message UL-DCCH-MessageType
+}
+
+UL-DCCH-MessageType ::= CHOICE {
+ c1 CHOICE {
+ csfbParametersRequestCDMA2000 CSFBParametersRequestCDMA2000,
+ measurementReport MeasurementReport,
+ rrcConnectionReconfigurationComplete RRCConnectionReconfigurationComplete,
+ rrcConnectionReestablishmentComplete RRCConnectionReestablishmentComplete,
+ rrcConnectionSetupComplete RRCConnectionSetupComplete,
+ securityModeComplete SecurityModeComplete,
+ securityModeFailure SecurityModeFailure,
+ ueCapabilityInformation UECapabilityInformation,
+ulHandoverPreparationTransfer ULHandoverPreparationTransfer,
+ ulInformationTransfer ULInformationTransfer,
+ counterCheckResponse CounterCheckResponse,
+ ueInformationResponse-r9 UEInformationResponse-r9,
+ proximityIndication-r9 ProximityIndication-r9,
+ spare3 NULL, spare2 NULL, spare1 NULL
+ },
+ messageClassExtension SEQUENCE {}
+}
+
+
+CounterCheck ::= SEQUENCE {
+ rrc-TransactionIdentifier RRC-TransactionIdentifier,
+ criticalExtensions CHOICE {
+ c1 CHOICE {
+ counterCheck-r8 CounterCheck-r8-IEs,
+ spare3 NULL, spare2 NULL, spare1 NULL
+ },
+ criticalExtensionsFuture SEQUENCE {}
+ }
+}
+
+CounterCheck-r8-IEs ::= SEQUENCE {
+ drb-CountMSB-InfoList DRB-CountMSB-InfoList,
+ nonCriticalExtension SEQUENCE {} OPTIONAL --Need OP
+}
+
+DRB-CountMSB-InfoList ::= SEQUENCE (SIZE (1..maxDRB)) OF DRB-CountMSB-Info
+
+DRB-CountMSB-Info ::= SEQUENCE {
+ drb-Identity DRB-Identity,
+ countMSB-Uplink INTEGER(0..33554431),
+ countMSB-Downlink INTEGER(0..33554431)
+}
+
+
+CounterCheckResponse ::= SEQUENCE {
+ rrc-TransactionIdentifier RRC-TransactionIdentifier,
+ criticalExtensions CHOICE {
+ counterCheckResponse-r8 CounterCheckResponse-r8-IEs,
+ criticalExtensionsFuture SEQUENCE {}
+ }
+}
+
+CounterCheckResponse-r8-IEs ::= SEQUENCE {
+ drb-CountInfoList DRB-CountInfoList,
+ nonCriticalExtension SEQUENCE {} OPTIONAL
+}
+
+DRB-CountInfoList ::= SEQUENCE (SIZE (0..maxDRB)) OF DRB-CountInfo
+
+DRB-CountInfo ::= SEQUENCE {
+ drb-Identity DRB-Identity,
+ count-Uplink INTEGER(0..4294967295),
+ count-Downlink INTEGER(0..4294967295)
+}
+
+
+CSFBParametersRequestCDMA2000 ::= SEQUENCE {
+ criticalExtensions CHOICE {
+ csfbParametersRequestCDMA2000-r8 CSFBParametersRequestCDMA2000-r8-IEs,
+ criticalExtensionsFuture SEQUENCE {}
+ }
+}
+
+CSFBParametersRequestCDMA2000-r8-IEs ::= SEQUENCE {
+ nonCriticalExtension SEQUENCE {} OPTIONAL
+}
+
+CSFBParametersResponseCDMA2000 ::= SEQUENCE {
+ rrc-TransactionIdentifier RRC-TransactionIdentifier,
+ criticalExtensions CHOICE {
+ csfbParametersResponseCDMA2000-r8 CSFBParametersResponseCDMA2000-r8-IEs,
+ criticalExtensionsFuture SEQUENCE {}
+ }
+}
+
+CSFBParametersResponseCDMA2000-r8-IEs ::= SEQUENCE {
+ rand RAND-CDMA2000,
+ mobilityParameters MobilityParametersCDMA2000,
+ nonCriticalExtension SEQUENCE {} OPTIONAL --Need OP
+}
+
+
+DLInformationTransfer ::= SEQUENCE {
+ rrc-TransactionIdentifier RRC-TransactionIdentifier,
+ criticalExtensions CHOICE {
+ c1 CHOICE {
+ dlInformationTransfer-r8 DLInformationTransfer-r8-IEs,
+ spare3 NULL, spare2 NULL, spare1 NULL
+ },
+ criticalExtensionsFuture SEQUENCE {}
+ }
+}
+
+DLInformationTransfer-r8-IEs ::= SEQUENCE {
+ dedicatedInfoType CHOICE {
+ dedicatedInfoNAS DedicatedInfoNAS,
+ dedicatedInfoCDMA2000-1XRTT DedicatedInfoCDMA2000,
+ dedicatedInfoCDMA2000-HRPD DedicatedInfoCDMA2000
+ },
+ nonCriticalExtension SEQUENCE {} OPTIONAL --Need OP
+}
+
+
+HandoverFromEUTRAPreparationRequest ::= SEQUENCE {
+ rrc-TransactionIdentifier RRC-TransactionIdentifier,
+ criticalExtensions CHOICE {
+ c1 CHOICE {
+ handoverFromEUTRAPreparationRequest-r8
+ HandoverFromEUTRAPreparationRequest-r8-IEs,
+ spare3 NULL, spare2 NULL, spare1 NULL
+ },
+ criticalExtensionsFuture SEQUENCE {}
+ }
+}
+
+HandoverFromEUTRAPreparationRequest-r8-IEs ::= SEQUENCE {
+ cdma2000-Type CDMA2000-Type,
+ rand RAND-CDMA2000 OPTIONAL, -- Cond cdma2000-Type
+ mobilityParameters MobilityParametersCDMA2000 OPTIONAL, -- Cond cdma2000-Type
+ nonCriticalExtension HandoverFromEUTRAPreparationRequest-v890-IEs OPTIONAL
+}
+
+HandoverFromEUTRAPreparationRequest-v890-IEs ::= SEQUENCE {
+ lateR8NonCriticalExtension OCTET STRING OPTIONAL, -- Need OP
+ nonCriticalExtension HandoverFromEUTRAPreparationRequest-v920-IEs OPTIONAL
+}
+
+HandoverFromEUTRAPreparationRequest-v920-IEs ::= SEQUENCE {
+ concurrPrepCDMA2000-HRPD-r9 BOOLEAN OPTIONAL, -- Cond PSHO
+ nonCriticalExtension SEQUENCE {} OPTIONAL -- Need OP
+}
+
+
+MasterInformationBlock ::= SEQUENCE {
+ dl-Bandwidth ENUMERATED {
+ n6, n15, n25, n50, n75, n100},
+ phich-Config PHICH-Config,
+ systemFrameNumber BIT STRING (SIZE (8)),
+ spare BIT STRING (SIZE (10))
+}
+
+
+
+MBSFNAreaConfiguration-r9 ::= SEQUENCE {
+ commonSF-Alloc-r9 CommonSF-AllocPatternList-r9,
+ commonSF-AllocPeriod-r9 ENUMERATED {
+ rf4, rf8, rf16, rf32, rf64, rf128, rf256},
+ pmch-InfoList-r9 PMCH-InfoList-r9,
+ nonCriticalExtension SEQUENCE {} OPTIONAL -- Need OP
+}
+
+CommonSF-AllocPatternList-r9 ::= SEQUENCE (SIZE (1..maxMBSFN-Allocations)) OF MBSFN-SubframeConfig
+
+
+MeasurementReport ::= SEQUENCE {
+ criticalExtensions CHOICE {
+ c1 CHOICE{
+ measurementReport-r8 MeasurementReport-r8-IEs,
+ spare7 NULL,
+ spare6 NULL, spare5 NULL, spare4 NULL,
+ spare3 NULL, spare2 NULL, spare1 NULL
+ },
+ criticalExtensionsFuture SEQUENCE {}
+ }
+}
+
+MeasurementReport-r8-IEs ::= SEQUENCE {
+ measResults MeasResults,
+ nonCriticalExtension SEQUENCE {} OPTIONAL
+}
+
+
+MobilityFromEUTRACommand ::= SEQUENCE {
+ rrc-TransactionIdentifier RRC-TransactionIdentifier,
+ criticalExtensions CHOICE {
+ c1 CHOICE{
+ mobilityFromEUTRACommand-r8 MobilityFromEUTRACommand-r8-IEs,
+ mobilityFromEUTRACommand-r9 MobilityFromEUTRACommand-r9-IEs,
+ spare2 NULL, spare1 NULL
+ },
+ criticalExtensionsFuture SEQUENCE {}
+ }
+}
+
+MobilityFromEUTRACommand-r8-IEs ::= SEQUENCE {
+ cs-FallbackIndicator BOOLEAN,
+ purpose CHOICE{
+ handover Handover,
+ cellChangeOrder CellChangeOrder
+ },
+ nonCriticalExtension SEQUENCE {} OPTIONAL -- Need OP
+}
+
+MobilityFromEUTRACommand-r9-IEs ::= SEQUENCE {
+ cs-FallbackIndicator BOOLEAN,
+ purpose CHOICE{
+ handover Handover,
+ cellChangeOrder CellChangeOrder,
+ e-CSFB-r9 E-CSFB-r9,
+ ...
+ },
+ nonCriticalExtension SEQUENCE {} OPTIONAL -- Need OP
+}
+
+Handover ::= SEQUENCE {
+ targetRAT-Type ENUMERATED {
+ utra, geran, cdma2000-1XRTT, cdma2000-HRPD,
+ spare4, spare3, spare2, spare1, ...},
+ targetRAT-MessageContainer OCTET STRING,
+ nas-SecurityParamFromEUTRA OCTET STRING (SIZE (1)) OPTIONAL, -- Cond UTRAGERAN
+ systemInformation SI-OrPSI-GERAN OPTIONAL -- Cond PSHO
+}
+
+CellChangeOrder ::= SEQUENCE {
+ t304 ENUMERATED {
+ ms100, ms200, ms500, ms1000,
+ ms2000, ms4000, ms8000, spare1},
+ targetRAT-Type CHOICE {
+ geran SEQUENCE {
+ physCellId PhysCellIdGERAN,
+ carrierFreq CarrierFreqGERAN,
+ networkControlOrder BIT STRING (SIZE (2)) OPTIONAL, -- Need OP
+ systemInformation SI-OrPSI-GERAN OPTIONAL -- Need OP
+ },
+ ...
+ }
+}
+
+SI-OrPSI-GERAN ::= CHOICE {
+ si SystemInfoListGERAN,
+ psi SystemInfoListGERAN
+}
+
+E-CSFB-r9 ::= SEQUENCE {
+ messageContCDMA2000-1XRTT-r9 OCTET STRING OPTIONAL, -- Need ON
+ mobilityCDMA2000-HRPD-r9 ENUMERATED {
+ handover, redirection
+ } OPTIONAL, -- Need OP
+ messageContCDMA2000-HRPD-r9 OCTET STRING OPTIONAL, -- Cond concHO
+ redirectCarrierCDMA2000-HRPD-r9 CarrierFreqCDMA2000 OPTIONAL -- Cond concRedir
+}
+
+
+Paging ::= SEQUENCE {
+ pagingRecordList PagingRecordList OPTIONAL, -- Need ON
+ systemInfoModification ENUMERATED {true} OPTIONAL, -- Need ON
+ etws-Indication ENUMERATED {true} OPTIONAL, -- Need ON
+ nonCriticalExtension Paging-v890-IEs OPTIONAL
+}
+
+Paging-v890-IEs ::= SEQUENCE {
+ lateR8NonCriticalExtension OCTET STRING OPTIONAL, -- Need OP
+ nonCriticalExtension Paging-v920-IEs OPTIONAL
+}
+
+Paging-v920-IEs ::= SEQUENCE {
+ cmas-Indication-r9 ENUMERATED {true} OPTIONAL, -- Need ON
+ nonCriticalExtension SEQUENCE {} OPTIONAL -- Need OP
+}
+
+PagingRecordList ::= SEQUENCE (SIZE (1..maxPageRec)) OF PagingRecord
+
+PagingRecord ::= SEQUENCE {
+ ue-Identity PagingUE-Identity,
+ cn-Domain ENUMERATED {ps, cs},
+ ...
+}
+
+PagingUE-Identity ::= CHOICE {
+ s-TMSI S-TMSI,
+ imsi IMSI,
+ ...
+}
+
+IMSI ::= SEQUENCE (SIZE (6..21)) OF IMSI-Digit
+
+IMSI-Digit ::= INTEGER (0..9)
+
+
+ProximityIndication-r9 ::= SEQUENCE {
+ criticalExtensions CHOICE {
+ c1 CHOICE {
+ proximityIndication-r9 ProximityIndication-r9-IEs,
+ spare3 NULL, spare2 NULL, spare1 NULL
+ },
+ criticalExtensionsFuture SEQUENCE {}
+ }
+}
+
+ProximityIndication-r9-IEs ::= SEQUENCE {
+ type-r9 ENUMERATED {entering, leaving},
+ carrierFreq-r9 CHOICE {
+ eutra-r9 ARFCN-ValueEUTRA,
+ utra-r9 ARFCN-ValueUTRA,
+ ...
+ },
+ nonCriticalExtension SEQUENCE {} OPTIONAL
+}
+
+
+RRCConnectionReconfiguration ::= SEQUENCE {
+ rrc-TransactionIdentifier RRC-TransactionIdentifier,
+ criticalExtensions CHOICE {
+ c1 CHOICE{
+ rrcConnectionReconfiguration-r8 RRCConnectionReconfiguration-r8-IEs,
+ spare7 NULL,
+ spare6 NULL, spare5 NULL, spare4 NULL,
+ spare3 NULL, spare2 NULL, spare1 NULL
+ },
+ criticalExtensionsFuture SEQUENCE {}
+ }
+}
+
+RRCConnectionReconfiguration-r8-IEs ::= SEQUENCE {
+ measConfig MeasConfig OPTIONAL, -- Need ON
+ mobilityControlInfo MobilityControlInfo OPTIONAL, -- Cond HO
+ dedicatedInfoNASList SEQUENCE (SIZE(1..maxDRB)) OF
+ DedicatedInfoNAS OPTIONAL, -- Cond nonHO
+ radioResourceConfigDedicated RadioResourceConfigDedicated OPTIONAL, -- Cond HO-toEUTRA
+ securityConfigHO SecurityConfigHO OPTIONAL, -- Cond HO
+ nonCriticalExtension RRCConnectionReconfiguration-v890-IEs OPTIONAL
+}
+
+RRCConnectionReconfiguration-v890-IEs ::= SEQUENCE {
+ lateR8NonCriticalExtension OCTET STRING OPTIONAL, -- Need OP
+ nonCriticalExtension RRCConnectionReconfiguration-v920-IEs OPTIONAL
+}
+
+RRCConnectionReconfiguration-v920-IEs ::= SEQUENCE {
+ otherConfig-r9 OtherConfig-r9 OPTIONAL, -- Need ON
+ fullConfig-r9 ENUMERATED {true} OPTIONAL, -- Cond HO-Reestab
+ nonCriticalExtension SEQUENCE {} OPTIONAL -- Need OP
+}
+
+SecurityConfigHO ::= SEQUENCE {
+ handoverType CHOICE {
+ intraLTE SEQUENCE {
+ securityAlgorithmConfig SecurityAlgorithmConfig OPTIONAL, -- Cond fullConfig
+ keyChangeIndicator BOOLEAN,
+ nextHopChainingCount NextHopChainingCount
+ },
+ interRAT SEQUENCE {
+ securityAlgorithmConfig SecurityAlgorithmConfig,
+ nas-SecurityParamToEUTRA OCTET STRING (SIZE(6))
+ }
+ },
+ ...
+}
+
+
+
+RRCConnectionReconfigurationComplete ::= SEQUENCE {
+ rrc-TransactionIdentifier RRC-TransactionIdentifier,
+ criticalExtensions CHOICE {
+ rrcConnectionReconfigurationComplete-r8
+ RRCConnectionReconfigurationComplete-r8-IEs,
+ criticalExtensionsFuture SEQUENCE {}
+ }
+}
+
+RRCConnectionReconfigurationComplete-r8-IEs ::= SEQUENCE {
+ nonCriticalExtension SEQUENCE {} OPTIONAL
+}
+
+
+RRCConnectionReestablishment ::= SEQUENCE {
+ rrc-TransactionIdentifier RRC-TransactionIdentifier,
+ criticalExtensions CHOICE {
+ c1 CHOICE{
+ rrcConnectionReestablishment-r8 RRCConnectionReestablishment-r8-IEs,
+ spare7 NULL,
+ spare6 NULL, spare5 NULL, spare4 NULL,
+ spare3 NULL, spare2 NULL, spare1 NULL
+ },
+ criticalExtensionsFuture SEQUENCE {}
+ }
+}
+
+RRCConnectionReestablishment-r8-IEs ::= SEQUENCE {
+ radioResourceConfigDedicated RadioResourceConfigDedicated,
+ nextHopChainingCount NextHopChainingCount,
+ nonCriticalExtension SEQUENCE {} OPTIONAL -- Need OP
+}
+
+
+RRCConnectionReestablishmentComplete ::= SEQUENCE {
+ rrc-TransactionIdentifier RRC-TransactionIdentifier,
+ criticalExtensions CHOICE {
+ rrcConnectionReestablishmentComplete-r8
+ RRCConnectionReestablishmentComplete-r8-IEs,
+ criticalExtensionsFuture SEQUENCE {}
+ }
+}
+
+RRCConnectionReestablishmentComplete-r8-IEs ::= SEQUENCE {
+ nonCriticalExtension RRCConnectionReestablishmentComplete-v920-IEs OPTIONAL
+}
+
+RRCConnectionReestablishmentComplete-v920-IEs ::= SEQUENCE {
+ rlf-InfoAvailable-r9 ENUMERATED {true} OPTIONAL,
+ nonCriticalExtension SEQUENCE {} OPTIONAL
+}
+
+
+RRCConnectionReestablishmentReject ::= SEQUENCE {
+ criticalExtensions CHOICE {
+ rrcConnectionReestablishmentReject-r8
+ RRCConnectionReestablishmentReject-r8-IEs,
+ criticalExtensionsFuture SEQUENCE {}
+ }
+}
+
+RRCConnectionReestablishmentReject-r8-IEs ::= SEQUENCE {
+ nonCriticalExtension SEQUENCE {} OPTIONAL -- Need OP
+}
+
+
+RRCConnectionReestablishmentRequest ::= SEQUENCE {
+ criticalExtensions CHOICE {
+ rrcConnectionReestablishmentRequest-r8
+ RRCConnectionReestablishmentRequest-r8-IEs,
+ criticalExtensionsFuture SEQUENCE {}
+ }
+}
+
+RRCConnectionReestablishmentRequest-r8-IEs ::= SEQUENCE {
+ ue-Identity ReestabUE-Identity,
+ reestablishmentCause ReestablishmentCause,
+ spare BIT STRING (SIZE (2))
+}
+
+ReestabUE-Identity ::= SEQUENCE {
+ c-RNTI C-RNTI,
+ physCellId PhysCellId,
+ shortMAC-I ShortMAC-I
+}
+
+ReestablishmentCause ::= ENUMERATED {
+ reconfigurationFailure, handoverFailure,
+ otherFailure, spare1}
+
+
+RRCConnectionReject ::= SEQUENCE {
+ criticalExtensions CHOICE {
+ c1 CHOICE {
+ rrcConnectionReject-r8 RRCConnectionReject-r8-IEs,
+ spare3 NULL, spare2 NULL, spare1 NULL
+ },
+ criticalExtensionsFuture SEQUENCE {}
+ }
+}
+
+RRCConnectionReject-r8-IEs ::= SEQUENCE {
+ waitTime INTEGER (1..16),
+ nonCriticalExtension SEQUENCE {} OPTIONAL -- Need OP
+}
+
+
+RRCConnectionRelease ::= SEQUENCE {
+ rrc-TransactionIdentifier RRC-TransactionIdentifier,
+ criticalExtensions CHOICE {
+ c1 CHOICE {
+ rrcConnectionRelease-r8 RRCConnectionRelease-r8-IEs,
+ spare3 NULL, spare2 NULL, spare1 NULL
+ },
+ criticalExtensionsFuture SEQUENCE {}
+ }
+}
+
+RRCConnectionRelease-r8-IEs ::= SEQUENCE {
+ releaseCause ReleaseCause,
+ redirectedCarrierInfo RedirectedCarrierInfo OPTIONAL, -- Need ON
+ idleModeMobilityControlInfo IdleModeMobilityControlInfo OPTIONAL, -- Need OP
+ nonCriticalExtension RRCConnectionRelease-v890-IEs OPTIONAL
+}
+
+RRCConnectionRelease-v890-IEs ::= SEQUENCE {
+ lateR8NonCriticalExtension OCTET STRING OPTIONAL, -- Need OP
+ nonCriticalExtension RRCConnectionRelease-v920-IEs OPTIONAL
+}
+
+RRCConnectionRelease-v920-IEs ::= SEQUENCE {
+ cellInfoList-r9 CHOICE {
+ geran-r9 CellInfoListGERAN-r9,
+ utra-FDD-r9 CellInfoListUTRA-FDD-r9,
+ utra-TDD-r9 CellInfoListUTRA-TDD-r9,
+ ...
+ } OPTIONAL, -- Cond Redirection
+ nonCriticalExtension SEQUENCE {} OPTIONAL -- Need OP
+}
+
+ReleaseCause ::= ENUMERATED {loadBalancingTAUrequired,
+ other,spare2,spare1}
+
+RedirectedCarrierInfo ::= CHOICE {
+ eutra ARFCN-ValueEUTRA,
+ geran CarrierFreqsGERAN,
+ utra-FDD ARFCN-ValueUTRA,
+ utra-TDD ARFCN-ValueUTRA,
+ cdma2000-HRPD CarrierFreqCDMA2000,
+ cdma2000-1xRTT CarrierFreqCDMA2000,
+ ...
+}
+
+IdleModeMobilityControlInfo ::= SEQUENCE {
+ freqPriorityListEUTRA FreqPriorityListEUTRA OPTIONAL, -- Need ON
+ freqPriorityListGERAN FreqsPriorityListGERAN OPTIONAL, -- Need ON
+ freqPriorityListUTRA-FDD FreqPriorityListUTRA-FDD OPTIONAL, -- Need ON
+ freqPriorityListUTRA-TDD FreqPriorityListUTRA-TDD OPTIONAL, -- Need ON
+ bandClassPriorityListHRPD BandClassPriorityListHRPD OPTIONAL, -- Need ON
+ bandClassPriorityList1XRTT BandClassPriorityList1XRTT OPTIONAL, -- Need ON
+ t320 ENUMERATED {
+ min5, min10, min20, min30, min60, min120, min180,
+ spare1} OPTIONAL, -- Need OR
+ ...
+}
+
+FreqPriorityListEUTRA ::= SEQUENCE (SIZE (1..maxFreq)) OF FreqPriorityEUTRA
+
+FreqPriorityEUTRA ::= SEQUENCE {
+ carrierFreq ARFCN-ValueEUTRA,
+ cellReselectionPriority CellReselectionPriority
+}
+
+FreqsPriorityListGERAN ::= SEQUENCE (SIZE (1..maxGNFG)) OF FreqsPriorityGERAN
+
+FreqsPriorityGERAN ::= SEQUENCE {
+ carrierFreqs CarrierFreqsGERAN,
+ cellReselectionPriority CellReselectionPriority
+}
+
+FreqPriorityListUTRA-FDD ::= SEQUENCE (SIZE (1..maxUTRA-FDD-Carrier)) OF FreqPriorityUTRA-FDD
+
+FreqPriorityUTRA-FDD ::= SEQUENCE {
+ carrierFreq ARFCN-ValueUTRA,
+ cellReselectionPriority CellReselectionPriority
+}
+
+FreqPriorityListUTRA-TDD ::= SEQUENCE (SIZE (1..maxUTRA-TDD-Carrier)) OF FreqPriorityUTRA-TDD
+
+FreqPriorityUTRA-TDD ::= SEQUENCE {
+ carrierFreq ARFCN-ValueUTRA,
+ cellReselectionPriority CellReselectionPriority
+}
+
+BandClassPriorityListHRPD ::= SEQUENCE (SIZE (1..maxCDMA-BandClass)) OF BandClassPriorityHRPD
+
+BandClassPriorityHRPD ::= SEQUENCE {
+ bandClass BandclassCDMA2000,
+ cellReselectionPriority CellReselectionPriority
+}
+
+BandClassPriorityList1XRTT ::= SEQUENCE (SIZE (1..maxCDMA-BandClass)) OF BandClassPriority1XRTT
+
+BandClassPriority1XRTT ::= SEQUENCE {
+ bandClass BandclassCDMA2000,
+ cellReselectionPriority CellReselectionPriority
+}
+
+CellInfoListGERAN-r9 ::= SEQUENCE (SIZE (1..maxCellInfo-GERAN-r9 )) OF CellInfoGERAN-r9
+
+CellInfoGERAN-r9 ::= SEQUENCE {
+ physCellId-r9 PhysCellIdGERAN,
+ carrierFreq-r9 CarrierFreqGERAN,
+ systemInformation-r9 SystemInfoListGERAN
+}
+
+CellInfoListUTRA-FDD-r9 ::= SEQUENCE (SIZE (1..maxUTRA-CellInfo-r9)) OF CellInfoUTRA-FDD-r9
+
+CellInfoUTRA-FDD-r9 ::= SEQUENCE {
+ physCellId-r9 PhysCellIdUTRA-FDD,
+ utra-BCCH-Container-r9 OCTET STRING
+}
+
+CellInfoListUTRA-TDD-r9 ::= SEQUENCE (SIZE (1..maxUTRA-CellInfo-r9)) OF CellInfoUTRA-TDD-r9
+
+CellInfoUTRA-TDD-r9 ::= SEQUENCE {
+ physCellId-r9 PhysCellIdUTRA-TDD,
+ utra-BCCH-Container-r9 OCTET STRING
+}
+
+
+RRCConnectionRequest ::= SEQUENCE {
+ criticalExtensions CHOICE {
+ rrcConnectionRequest-r8 RRCConnectionRequest-r8-IEs,
+ criticalExtensionsFuture SEQUENCE {}
+ }
+}
+
+RRCConnectionRequest-r8-IEs ::= SEQUENCE {
+ ue-Identity InitialUE-Identity,
+ establishmentCause EstablishmentCause,
+ spare BIT STRING (SIZE (1))
+}
+
+InitialUE-Identity ::= CHOICE {
+ s-TMSI S-TMSI,
+ randomValue BIT STRING (SIZE (40))
+}
+
+EstablishmentCause ::= ENUMERATED {
+ emergency, highPriorityAccess, mt-Access, mo-Signalling,
+ mo-Data, spare3, spare2, spare1}
+
+
+RRCConnectionSetup ::= SEQUENCE {
+ rrc-TransactionIdentifier RRC-TransactionIdentifier,
+ criticalExtensions CHOICE {
+ c1 CHOICE {
+ rrcConnectionSetup-r8 RRCConnectionSetup-r8-IEs,
+ spare7 NULL,
+ spare6 NULL, spare5 NULL, spare4 NULL,
+ spare3 NULL, spare2 NULL, spare1 NULL
+ },
+ criticalExtensionsFuture SEQUENCE {}
+ }
+}
+
+RRCConnectionSetup-r8-IEs ::= SEQUENCE {
+ radioResourceConfigDedicated RadioResourceConfigDedicated,
+ nonCriticalExtension SEQUENCE {} OPTIONAL -- Need OP
+}
+
+
+RRCConnectionSetupComplete ::= SEQUENCE {
+ rrc-TransactionIdentifier RRC-TransactionIdentifier,
+ criticalExtensions CHOICE {
+ c1 CHOICE{
+ rrcConnectionSetupComplete-r8 RRCConnectionSetupComplete-r8-IEs,
+ spare3 NULL, spare2 NULL, spare1 NULL
+ },
+ criticalExtensionsFuture SEQUENCE {}
+ }
+}
+
+RRCConnectionSetupComplete-r8-IEs ::= SEQUENCE {
+ selectedPLMN-Identity INTEGER (1..6),
+ registeredMME RegisteredMME OPTIONAL,
+ dedicatedInfoNAS DedicatedInfoNAS,
+ nonCriticalExtension SEQUENCE {} OPTIONAL
+}
+
+RegisteredMME ::= SEQUENCE {
+ plmn-Identity PLMN-Identity OPTIONAL,
+ mmegi BIT STRING (SIZE (16)),
+ mmec MMEC
+}
+
+
+SecurityModeCommand ::= SEQUENCE {
+ rrc-TransactionIdentifier RRC-TransactionIdentifier,
+ criticalExtensions CHOICE {
+ c1 CHOICE{
+ securityModeCommand-r8 SecurityModeCommand-r8-IEs,
+ spare3 NULL, spare2 NULL, spare1 NULL
+ },
+ criticalExtensionsFuture SEQUENCE {}
+ }
+}
+
+SecurityModeCommand-r8-IEs ::= SEQUENCE {
+ securityConfigSMC SecurityConfigSMC,
+ nonCriticalExtension SEQUENCE {} OPTIONAL -- Need OP
+}
+
+SecurityConfigSMC ::= SEQUENCE {
+ securityAlgorithmConfig SecurityAlgorithmConfig,
+ ...
+}
+
+
+SecurityModeComplete ::= SEQUENCE {
+ rrc-TransactionIdentifier RRC-TransactionIdentifier,
+ criticalExtensions CHOICE {
+ securityModeComplete-r8 SecurityModeComplete-r8-IEs,
+ criticalExtensionsFuture SEQUENCE {}
+ }
+}
+
+SecurityModeComplete-r8-IEs ::= SEQUENCE {
+ nonCriticalExtension SEQUENCE {} OPTIONAL
+}
+
+
+SecurityModeFailure ::= SEQUENCE {
+ rrc-TransactionIdentifier RRC-TransactionIdentifier,
+ criticalExtensions CHOICE {
+ securityModeFailure-r8 SecurityModeFailure-r8-IEs,
+ criticalExtensionsFuture SEQUENCE {}
+ }
+}
+
+SecurityModeFailure-r8-IEs ::= SEQUENCE {
+ nonCriticalExtension SEQUENCE {} OPTIONAL
+}
+
+
+SystemInformation ::= SEQUENCE {
+ criticalExtensions CHOICE {
+ systemInformation-r8 SystemInformation-r8-IEs,
+ criticalExtensionsFuture SEQUENCE {}
+ }
+}
+SystemInformation-r8-IEs ::= SEQUENCE {
+ sib-TypeAndInfo SEQUENCE (SIZE (1..maxSIB)) OF CHOICE {
+ sib2 SystemInformationBlockType2,
+ sib3 SystemInformationBlockType3,
+ sib4 SystemInformationBlockType4,
+ sib5 SystemInformationBlockType5,
+ sib6 SystemInformationBlockType6,
+ sib7 SystemInformationBlockType7,
+ sib8 SystemInformationBlockType8,
+ sib9 SystemInformationBlockType9,
+ sib10 SystemInformationBlockType10,
+ sib11 SystemInformationBlockType11,
+ ...,
+ sib12-v920 SystemInformationBlockType12-r9,
+ sib13-v920 SystemInformationBlockType13-r9
+ },
+ nonCriticalExtension SEQUENCE {} OPTIONAL -- Need OP
+}
+
+
+SystemInformationBlockType1 ::= SEQUENCE {
+ cellAccessRelatedInfo SEQUENCE {
+ plmn-IdentityList PLMN-IdentityList,
+ trackingAreaCode TrackingAreaCode,
+ cellIdentity CellIdentity,
+ cellBarred ENUMERATED {barred, notBarred},
+ intraFreqReselection ENUMERATED {allowed, notAllowed},
+ csg-Indication BOOLEAN,
+ csg-Identity CSG-Identity OPTIONAL -- Need OR
+ },
+ cellSelectionInfo SEQUENCE {
+ q-RxLevMin Q-RxLevMin,
+ q-RxLevMinOffset INTEGER (1..8) OPTIONAL -- Need OP
+ },
+ p-Max P-Max OPTIONAL, -- Need OP
+ freqBandIndicator INTEGER (1..64),
+ schedulingInfoList SchedulingInfoList,
+ tdd-Config TDD-Config OPTIONAL, -- Cond TDD
+ si-WindowLength ENUMERATED {
+ ms1, ms2, ms5, ms10, ms15, ms20,
+ ms40},
+ systemInfoValueTag INTEGER (0..31),
+ nonCriticalExtension SystemInformationBlockType1-v890-IEs OPTIONAL
+}
+
+SystemInformationBlockType1-v890-IEs::= SEQUENCE {
+ lateR8NonCriticalExtension OCTET STRING OPTIONAL, -- Need OP
+ nonCriticalExtension SystemInformationBlockType1-v920-IEs OPTIONAL
+}
+
+SystemInformationBlockType1-v920-IEs ::= SEQUENCE {
+ ims-EmergencySupport-r9 ENUMERATED {true} OPTIONAL, -- Need OR
+ cellSelectionInfo-v920 CellSelectionInfo-v920 OPTIONAL, -- Need OP
+ nonCriticalExtension SEQUENCE {} OPTIONAL -- Need OP
+}
+
+PLMN-IdentityList ::= SEQUENCE (SIZE (1..6)) OF PLMN-IdentityInfo
+
+PLMN-IdentityInfo ::= SEQUENCE {
+ plmn-Identity PLMN-Identity,
+ cellReservedForOperatorUse ENUMERATED {reserved, notReserved}
+}
+
+SchedulingInfoList ::= SEQUENCE (SIZE (1..maxSI-Message)) OF SchedulingInfo
+
+SchedulingInfo ::= SEQUENCE {
+ si-Periodicity ENUMERATED {
+ rf8, rf16, rf32, rf64, rf128, rf256, rf512},
+ sib-MappingInfo SIB-MappingInfo
+}
+
+SIB-MappingInfo ::= SEQUENCE (SIZE (0..maxSIB-1)) OF SIB-Type
+
+SIB-Type ::= ENUMERATED {
+ sibType3, sibType4, sibType5, sibType6,
+ sibType7, sibType8, sibType9, sibType10,
+ sibType11, sibType12-v920, sibType13-v920, spare5,
+ spare4, spare3, spare2, spare1, ...}
+
+CellSelectionInfo-v920 ::= SEQUENCE {
+ q-QualMin-r9 Q-QualMin-r9,
+ q-QualMinOffset-r9 INTEGER (1..8) OPTIONAL -- Need OP
+}
+
+
+UECapabilityEnquiry ::= SEQUENCE {
+ rrc-TransactionIdentifier RRC-TransactionIdentifier,
+ criticalExtensions CHOICE {
+ c1 CHOICE {
+ ueCapabilityEnquiry-r8 UECapabilityEnquiry-r8-IEs,
+ spare3 NULL, spare2 NULL, spare1 NULL
+ },
+ criticalExtensionsFuture SEQUENCE {}
+ }
+}
+
+UECapabilityEnquiry-r8-IEs ::= SEQUENCE {
+ ue-CapabilityRequest UE-CapabilityRequest,
+ nonCriticalExtension SEQUENCE {} OPTIONAL -- Need OP
+}
+
+UE-CapabilityRequest ::= SEQUENCE (SIZE (1..maxRAT-Capabilities)) OF RAT-Type
+
+
+UECapabilityInformation ::= SEQUENCE {
+ rrc-TransactionIdentifier RRC-TransactionIdentifier,
+ criticalExtensions CHOICE {
+ c1 CHOICE{
+ ueCapabilityInformation-r8 UECapabilityInformation-r8-IEs,
+ spare7 NULL,
+ spare6 NULL, spare5 NULL, spare4 NULL,
+ spare3 NULL, spare2 NULL, spare1 NULL
+ },
+ criticalExtensionsFuture SEQUENCE {}
+ }
+}
+
+UECapabilityInformation-r8-IEs ::= SEQUENCE {
+ ue-CapabilityRAT-ContainerList UE-CapabilityRAT-ContainerList,
+ nonCriticalExtension SEQUENCE {} OPTIONAL
+}
+
+
+UEInformationRequest-r9 ::= SEQUENCE {
+ rrc-TransactionIdentifier RRC-TransactionIdentifier,
+ criticalExtensions CHOICE {
+ c1 CHOICE {
+ ueInformationRequest-r9 UEInformationRequest-r9-IEs,
+ spare3 NULL, spare2 NULL, spare1 NULL
+ },
+ criticalExtensionsFuture SEQUENCE {}
+ }
+}
+
+UEInformationRequest-r9-IEs ::= SEQUENCE {
+ rach-ReportReq-r9 BOOLEAN,
+ rlf-ReportReq-r9 BOOLEAN,
+ nonCriticalExtension SEQUENCE {} OPTIONAL -- Need OP
+}
+
+
+UEInformationResponse-r9 ::= SEQUENCE {
+ rrc-TransactionIdentifier RRC-TransactionIdentifier,
+ criticalExtensions CHOICE {
+ c1 CHOICE {
+ ueInformationResponse-r9 UEInformationResponse-r9-IEs,
+ spare3 NULL, spare2 NULL, spare1 NULL
+ },
+ criticalExtensionsFuture SEQUENCE {}
+ }
+}
+
+UEInformationResponse-r9-IEs ::= SEQUENCE {
+ rach-Report-r9 SEQUENCE {
+ numberOfPreamblesSent-r9 INTEGER (1..200),
+ contentionDetected-r9 BOOLEAN
+ } OPTIONAL,
+ rlfReport-r9 RLF-Report-r9 OPTIONAL,
+ nonCriticalExtension SEQUENCE {} OPTIONAL
+}
+
+RLF-Report-r9 ::= SEQUENCE {
+ measResultLastServCell SEQUENCE {
+ rsrpResult RSRP-Range,
+ rsrqResult RSRQ-Range OPTIONAL
+ },
+ measResultNeighCells SEQUENCE {
+ measResultListEUTRA MeasResultList2EUTRA OPTIONAL,
+ measResultListUTRA MeasResultList2UTRA OPTIONAL,
+ measResultListGERAN MeasResultListGERAN OPTIONAL,
+ measResultsCDMA2000 MeasResultList2CDMA2000 OPTIONAL
+ } OPTIONAL,
+ ...
+}
+
+MeasResultList2EUTRA ::= SEQUENCE (SIZE (1..maxFreq)) OF SEQUENCE {
+ carrierFreq ARFCN-ValueEUTRA,
+ measResultList MeasResultListEUTRA
+}
+
+MeasResultList2UTRA ::= SEQUENCE (SIZE (1..maxCellReport)) OF SEQUENCE {
+ carrierFreq ARFCN-ValueUTRA,
+ measResultList MeasResultListUTRA
+}
+
+MeasResultList2CDMA2000 ::= SEQUENCE (SIZE (1..maxCellReport)) OF SEQUENCE {
+ carrierFreq CarrierFreqCDMA2000,
+ measResultList MeasResultsCDMA2000
+}
+
+
+ULHandoverPreparationTransfer ::= SEQUENCE {
+ criticalExtensions CHOICE {
+ c1 CHOICE {
+ ulHandoverPreparationTransfer-r8 ULHandoverPreparationTransfer-r8-IEs,
+ spare3 NULL, spare2 NULL, spare1 NULL
+ },
+ criticalExtensionsFuture SEQUENCE {}
+ }
+}
+
+ULHandoverPreparationTransfer-r8-IEs ::= SEQUENCE {
+ cdma2000-Type CDMA2000-Type,
+ meid BIT STRING (SIZE (56)) OPTIONAL,
+ dedicatedInfo DedicatedInfoCDMA2000,
+ nonCriticalExtension SEQUENCE {} OPTIONAL
+}
+
+
+ULInformationTransfer ::= SEQUENCE {
+ criticalExtensions CHOICE {
+ c1 CHOICE {
+ ulInformationTransfer-r8 ULInformationTransfer-r8-IEs,
+ spare3 NULL, spare2 NULL, spare1 NULL
+ },
+ criticalExtensionsFuture SEQUENCE {}
+ }
+}
+
+ULInformationTransfer-r8-IEs ::= SEQUENCE {
+ dedicatedInfoType CHOICE {
+ dedicatedInfoNAS DedicatedInfoNAS,
+ dedicatedInfoCDMA2000-1XRTT DedicatedInfoCDMA2000,
+ dedicatedInfoCDMA2000-HRPD DedicatedInfoCDMA2000
+ },
+ nonCriticalExtension SEQUENCE {} OPTIONAL
+}
+
+
+SystemInformationBlockType2 ::= SEQUENCE {
+ ac-BarringInfo SEQUENCE {
+ ac-BarringForEmergency BOOLEAN,
+ ac-BarringForMO-Signalling AC-BarringConfig OPTIONAL, -- Need OP
+ ac-BarringForMO-Data AC-BarringConfig OPTIONAL -- Need OP
+ } OPTIONAL, -- Need OP
+ radioResourceConfigCommon RadioResourceConfigCommonSIB,
+ ue-TimersAndConstants UE-TimersAndConstants,
+ freqInfo SEQUENCE {
+ ul-CarrierFreq ARFCN-ValueEUTRA OPTIONAL, -- Need OP
+ ul-Bandwidth ENUMERATED {n6, n15, n25, n50, n75, n100}
+ OPTIONAL, -- Need OP
+ additionalSpectrumEmission AdditionalSpectrumEmission
+ },
+ mbsfn-SubframeConfigList MBSFN-SubframeConfigList OPTIONAL, -- Need OR
+ timeAlignmentTimerCommon TimeAlignmentTimer,
+ ...,
+ lateR8NonCriticalExtension OCTET STRING OPTIONAL, -- Need OP
+ [[ ssac-BarringForMMTEL-Voice-r9 AC-BarringConfig OPTIONAL, -- Need OP
+ ssac-BarringForMMTEL-Video-r9 AC-BarringConfig OPTIONAL -- Need OP
+ ]]
+}
+
+AC-BarringConfig ::= SEQUENCE {
+ ac-BarringFactor ENUMERATED {
+ p00, p05, p10, p15, p20, p25, p30, p40,
+ p50, p60, p70, p75, p80, p85, p90, p95},
+ ac-BarringTime ENUMERATED {s4, s8, s16, s32, s64, s128, s256, s512},
+ ac-BarringForSpecialAC BIT STRING (SIZE(5))
+}
+
+MBSFN-SubframeConfigList ::= SEQUENCE (SIZE (1..maxMBSFN-Allocations)) OF MBSFN-SubframeConfig
+
+
+SystemInformationBlockType3 ::= SEQUENCE {
+ cellReselectionInfoCommon SEQUENCE {
+ q-Hyst ENUMERATED {
+ dB0, dB1, dB2, dB3, dB4, dB5, dB6, dB8, dB10,
+ dB12, dB14, dB16, dB18, dB20, dB22, dB24},
+ speedStateReselectionPars SEQUENCE {
+ mobilityStateParameters MobilityStateParameters,
+ q-HystSF SEQUENCE {
+ sf-Medium ENUMERATED {
+ dB-6, dB-4, dB-2, dB0},
+ sf-High ENUMERATED {
+ dB-6, dB-4, dB-2, dB0}
+ }
+ } OPTIONAL -- Need OP
+ },
+ cellReselectionServingFreqInfo SEQUENCE {
+ s-NonIntraSearch ReselectionThreshold OPTIONAL, -- Need OP
+ threshServingLow ReselectionThreshold,
+ cellReselectionPriority CellReselectionPriority
+ },
+ intraFreqCellReselectionInfo SEQUENCE {
+ q-RxLevMin Q-RxLevMin,
+ p-Max P-Max OPTIONAL, -- Need OP
+ s-IntraSearch ReselectionThreshold OPTIONAL, -- Need OP
+ allowedMeasBandwidth AllowedMeasBandwidth OPTIONAL, -- Need OP
+ presenceAntennaPort1 PresenceAntennaPort1,
+ neighCellConfig NeighCellConfig,
+ t-ReselectionEUTRA T-Reselection,
+ t-ReselectionEUTRA-SF SpeedStateScaleFactors OPTIONAL -- Need OP
+ },
+ ...,
+ lateR8NonCriticalExtension OCTET STRING OPTIONAL, -- Need OP
+ [[ s-IntraSearch-v920 SEQUENCE {
+ s-IntraSearchP-r9 ReselectionThreshold,
+ s-IntraSearchQ-r9 ReselectionThresholdQ-r9
+ } OPTIONAL, -- Need OP
+ s-NonIntraSearch-v920 SEQUENCE {
+ s-NonIntraSearchP-r9 ReselectionThreshold,
+ s-NonIntraSearchQ-r9 ReselectionThresholdQ-r9
+ } OPTIONAL, -- Need OP
+ q-QualMin-r9 Q-QualMin-r9 OPTIONAL, -- Need OP
+ threshServingLowQ-r9 ReselectionThresholdQ-r9 OPTIONAL -- Need OP
+ ]]
+}
+
+
+SystemInformationBlockType4 ::= SEQUENCE {
+ intraFreqNeighCellList IntraFreqNeighCellList OPTIONAL, -- Need OR
+ intraFreqBlackCellList IntraFreqBlackCellList OPTIONAL, -- Need OR
+ csg-PhysCellIdRange PhysCellIdRange OPTIONAL, -- Cond CSG
+ ...
+}
+
+IntraFreqNeighCellList ::= SEQUENCE (SIZE (1..maxCellIntra)) OF IntraFreqNeighCellInfo
+
+IntraFreqNeighCellInfo ::= SEQUENCE {
+ physCellId PhysCellId,
+ q-OffsetCell Q-OffsetRange,
+ ...
+}
+
+IntraFreqBlackCellList ::= SEQUENCE (SIZE (1..maxCellBlack)) OF PhysCellIdRange
+
+
+SystemInformationBlockType5 ::= SEQUENCE {
+ interFreqCarrierFreqList InterFreqCarrierFreqList,
+ ...,
+ lateR8NonCriticalExtension OCTET STRING OPTIONAL -- Need OP
+}
+
+InterFreqCarrierFreqList ::= SEQUENCE (SIZE (1..maxFreq)) OF InterFreqCarrierFreqInfo
+
+InterFreqCarrierFreqInfo ::= SEQUENCE {
+ dl-CarrierFreq ARFCN-ValueEUTRA,
+ q-RxLevMin Q-RxLevMin,
+ p-Max P-Max OPTIONAL, -- Need OP
+ t-ReselectionEUTRA T-Reselection,
+ t-ReselectionEUTRA-SF SpeedStateScaleFactors OPTIONAL, -- Need OP
+ threshX-High ReselectionThreshold,
+ threshX-Low ReselectionThreshold,
+ allowedMeasBandwidth AllowedMeasBandwidth,
+ presenceAntennaPort1 PresenceAntennaPort1,
+ cellReselectionPriority CellReselectionPriority OPTIONAL, -- Need OP
+ neighCellConfig NeighCellConfig,
+ q-OffsetFreq Q-OffsetRange DEFAULT dB0,
+ interFreqNeighCellList InterFreqNeighCellList OPTIONAL, -- Need OR
+ interFreqBlackCellList InterFreqBlackCellList OPTIONAL, -- Need OR
+ ...,
+ [[ q-QualMin-r9 Q-QualMin-r9 OPTIONAL, -- Need OP
+ threshX-Q-r9 SEQUENCE {
+ threshX-HighQ-r9 ReselectionThresholdQ-r9,
+ threshX-LowQ-r9 ReselectionThresholdQ-r9
+ } OPTIONAL -- Cond RSRQ
+ ]]
+}
+
+InterFreqNeighCellList ::= SEQUENCE (SIZE (1..maxCellInter)) OF InterFreqNeighCellInfo
+
+InterFreqNeighCellInfo ::= SEQUENCE {
+ physCellId PhysCellId,
+ q-OffsetCell Q-OffsetRange
+}
+
+InterFreqBlackCellList ::= SEQUENCE (SIZE (1..maxCellBlack)) OF PhysCellIdRange
+
+
+SystemInformationBlockType6 ::= SEQUENCE {
+ carrierFreqListUTRA-FDD CarrierFreqListUTRA-FDD OPTIONAL, -- Need OR
+ carrierFreqListUTRA-TDD CarrierFreqListUTRA-TDD OPTIONAL, -- Need OR
+ t-ReselectionUTRA T-Reselection,
+ t-ReselectionUTRA-SF SpeedStateScaleFactors OPTIONAL, -- Need OP
+ ...,
+ lateR8NonCriticalExtension OCTET STRING OPTIONAL -- Need OP
+}
+
+CarrierFreqListUTRA-FDD ::= SEQUENCE (SIZE (1..maxUTRA-FDD-Carrier)) OF CarrierFreqUTRA-FDD
+
+CarrierFreqUTRA-FDD ::= SEQUENCE {
+ carrierFreq ARFCN-ValueUTRA,
+ cellReselectionPriority CellReselectionPriority OPTIONAL, -- Need OP
+ threshX-High ReselectionThreshold,
+ threshX-Low ReselectionThreshold,
+ q-RxLevMin INTEGER (-60..-13),
+ p-MaxUTRA INTEGER (-50..33),
+ q-QualMin INTEGER (-24..0),
+ ...,
+ [[ threshX-Q-r9 SEQUENCE {
+ threshX-HighQ-r9 ReselectionThresholdQ-r9,
+ threshX-LowQ-r9 ReselectionThresholdQ-r9
+ } OPTIONAL -- Cond RSRQ
+ ]]
+}
+
+CarrierFreqListUTRA-TDD ::= SEQUENCE (SIZE (1..maxUTRA-TDD-Carrier)) OF CarrierFreqUTRA-TDD
+
+CarrierFreqUTRA-TDD ::= SEQUENCE {
+ carrierFreq ARFCN-ValueUTRA,
+ cellReselectionPriority CellReselectionPriority OPTIONAL, -- Need OP
+ threshX-High ReselectionThreshold,
+ threshX-Low ReselectionThreshold,
+ q-RxLevMin INTEGER (-60..-13),
+ p-MaxUTRA INTEGER (-50..33),
+ ...
+}
+
+
+SystemInformationBlockType7 ::= SEQUENCE {
+ t-ReselectionGERAN T-Reselection,
+ t-ReselectionGERAN-SF SpeedStateScaleFactors OPTIONAL, -- Need OR
+ carrierFreqsInfoList CarrierFreqsInfoListGERAN OPTIONAL, -- Need OR
+ ...
+}
+
+CarrierFreqsInfoListGERAN ::= SEQUENCE (SIZE (1..maxGNFG)) OF CarrierFreqsInfoGERAN
+
+CarrierFreqsInfoGERAN ::= SEQUENCE {
+ carrierFreqs CarrierFreqsGERAN,
+ commonInfo SEQUENCE {
+ cellReselectionPriority CellReselectionPriority OPTIONAL, -- Need OP
+ ncc-Permitted BIT STRING (SIZE (8)),
+ q-RxLevMin INTEGER (0..45),
+ p-MaxGERAN INTEGER (0..39) OPTIONAL, -- Need OP
+ threshX-High ReselectionThreshold,
+ threshX-Low ReselectionThreshold
+ },
+ ...
+}
+
+
+SystemInformationBlockType8 ::= SEQUENCE {
+ systemTimeInfo SystemTimeInfoCDMA2000 OPTIONAL, -- Need OR
+ searchWindowSize INTEGER (0..15) OPTIONAL, -- Need OR
+ parametersHRPD SEQUENCE {
+ preRegistrationInfoHRPD PreRegistrationInfoHRPD,
+ cellReselectionParametersHRPD CellReselectionParametersCDMA2000 OPTIONAL -- Need OR
+ } OPTIONAL, -- Need OR
+ parameters1XRTT SEQUENCE {
+ csfb-RegistrationParam1XRTT CSFB-RegistrationParam1XRTT OPTIONAL, -- Need OP
+ longCodeState1XRTT BIT STRING (SIZE (42)) OPTIONAL, -- Need OR
+ cellReselectionParameters1XRTT CellReselectionParametersCDMA2000 OPTIONAL -- Need OR
+ } OPTIONAL, -- Need OR
+ ...,
+ lateR8NonCriticalExtension OCTET STRING OPTIONAL, -- Need OP
+ [[ csfb-SupportForDualRxUEs-r9 BOOLEAN OPTIONAL, -- Need OR
+ cellReselectionParametersHRPD-v920 CellReselectionParametersCDMA2000-v920 OPTIONAL, -- Cond NCL-HRPD
+ cellReselectionParameters1XRTT-v920 CellReselectionParametersCDMA2000-v920 OPTIONAL, -- Cond NCL-1XRTT
+ csfb-RegistrationParam1XRTT-v920 CSFB-RegistrationParam1XRTT-v920 OPTIONAL, -- Cond REG-1XRTT
+ ac-BarringConfig1XRTT-r9 AC-BarringConfig1XRTT-r9 OPTIONAL -- Cond REG-1XRTT
+ ]]
+}
+
+CellReselectionParametersCDMA2000 ::= SEQUENCE {
+ bandClassList BandClassListCDMA2000,
+ neighCellList NeighCellListCDMA2000,
+ t-ReselectionCDMA2000 T-Reselection,
+ t-ReselectionCDMA2000-SF SpeedStateScaleFactors OPTIONAL -- Need OP
+}
+
+CellReselectionParametersCDMA2000-v920 ::= SEQUENCE {
+ neighCellList-v920 NeighCellListCDMA2000-v920
+}
+
+NeighCellListCDMA2000 ::= SEQUENCE (SIZE (1..16)) OF NeighCellCDMA2000
+
+NeighCellCDMA2000 ::= SEQUENCE {
+ bandClass BandclassCDMA2000,
+ neighCellsPerFreqList NeighCellsPerBandclassListCDMA2000
+}
+
+NeighCellsPerBandclassListCDMA2000 ::= SEQUENCE (SIZE (1..16)) OF NeighCellsPerBandclassCDMA2000
+
+NeighCellsPerBandclassCDMA2000 ::= SEQUENCE {
+ arfcn ARFCN-ValueCDMA2000,
+ physCellIdList PhysCellIdListCDMA2000
+}
+
+NeighCellListCDMA2000-v920 ::= SEQUENCE (SIZE (1..16)) OF NeighCellCDMA2000-v920
+
+NeighCellCDMA2000-v920 ::= SEQUENCE {
+ neighCellsPerFreqList-v920 NeighCellsPerBandclassListCDMA2000-v920
+}
+
+NeighCellsPerBandclassListCDMA2000-v920 ::= SEQUENCE (SIZE (1..16)) OF NeighCellsPerBandclassCDMA2000-v920
+
+NeighCellsPerBandclassCDMA2000-v920 ::= SEQUENCE {
+ physCellIdList-v920 PhysCellIdListCDMA2000-v920
+}
+
+PhysCellIdListCDMA2000 ::= SEQUENCE (SIZE (1..16)) OF PhysCellIdCDMA2000
+
+PhysCellIdListCDMA2000-v920 ::= SEQUENCE (SIZE (0..24)) OF PhysCellIdCDMA2000
+
+BandClassListCDMA2000 ::= SEQUENCE (SIZE (1..maxCDMA-BandClass)) OF BandClassInfoCDMA2000
+
+BandClassInfoCDMA2000 ::= SEQUENCE {
+ bandClass BandclassCDMA2000,
+ cellReselectionPriority CellReselectionPriority OPTIONAL, -- Need OP
+ threshX-High INTEGER (0..63),
+ threshX-Low INTEGER (0..63),
+ ...
+}
+
+AC-BarringConfig1XRTT-r9 ::= SEQUENCE {
+ ac-Barring0to9-r9 INTEGER (0..63),
+ ac-Barring10-r9 INTEGER (0..7),
+ ac-Barring11-r9 INTEGER (0..7),
+ ac-Barring12-r9 INTEGER (0..7),
+ ac-Barring13-r9 INTEGER (0..7),
+ ac-Barring14-r9 INTEGER (0..7),
+ ac-Barring15-r9 INTEGER (0..7),
+ ac-BarringMsg-r9 INTEGER (0..7),
+ ac-BarringReg-r9 INTEGER (0..7),
+ ac-BarringEmg-r9 INTEGER (0..7)
+}
+
+
+SystemInformationBlockType9 ::= SEQUENCE {
+ hnb-Name OCTET STRING (SIZE(1..48)) OPTIONAL, -- Need OR
+ ...
+}
+
+
+SystemInformationBlockType10 ::= SEQUENCE {
+ messageIdentifier BIT STRING (SIZE (16)),
+ serialNumber BIT STRING (SIZE (16)),
+ warningType OCTET STRING (SIZE (2)),
+ warningSecurityInfo OCTET STRING (SIZE (50)) OPTIONAL, -- Need OP
+ ...
+}
+
+
+SystemInformationBlockType11 ::= SEQUENCE {
+ messageIdentifier BIT STRING (SIZE (16)),
+ serialNumber BIT STRING (SIZE (16)),
+ warningMessageSegmentType ENUMERATED {notLastSegment, lastSegment},
+ warningMessageSegmentNumber INTEGER (0..63),
+ warningMessageSegment OCTET STRING,
+ dataCodingScheme OCTET STRING (SIZE (1)) OPTIONAL, -- Cond Segment1
+ ...
+}
+
+
+SystemInformationBlockType12-r9 ::= SEQUENCE {
+ messageIdentifier-r9 BIT STRING (SIZE (16)),
+ serialNumber-r9 BIT STRING (SIZE (16)),
+ warningMessageSegmentType-r9 ENUMERATED {notLastSegment, lastSegment},
+ warningMessageSegmentNumber-r9 INTEGER (0..63),
+ warningMessageSegment-r9 OCTET STRING,
+ dataCodingScheme-r9 OCTET STRING (SIZE (1)) OPTIONAL, -- Cond Segment1
+ lateR9NonCriticalExtension OCTET STRING OPTIONAL, -- Need OP
+ ...
+}
+
+
+SystemInformationBlockType13-r9 ::= SEQUENCE {
+ mbsfn-AreaInfoList-r9 MBSFN-AreaInfoList-r9,
+ notificationConfig-r9 MBMS-NotificationConfig-r9,
+ lateR9NonCriticalExtension OCTET STRING OPTIONAL, -- Need OP
+ ...
+}
+
+
+AntennaInfoCommon ::= SEQUENCE {
+ antennaPortsCount ENUMERATED {an1, an2, an4, spare1}
+}
+
+AntennaInfoDedicated ::= SEQUENCE {
+ transmissionMode ENUMERATED {
+ tm1, tm2, tm3, tm4, tm5, tm6,
+ tm7, tm8-v920},
+ codebookSubsetRestriction CHOICE {
+ n2TxAntenna-tm3 BIT STRING (SIZE (2)),
+ n4TxAntenna-tm3 BIT STRING (SIZE (4)),
+ n2TxAntenna-tm4 BIT STRING (SIZE (6)),
+ n4TxAntenna-tm4 BIT STRING (SIZE (64)),
+ n2TxAntenna-tm5 BIT STRING (SIZE (4)),
+ n4TxAntenna-tm5 BIT STRING (SIZE (16)),
+ n2TxAntenna-tm6 BIT STRING (SIZE (4)),
+ n4TxAntenna-tm6 BIT STRING (SIZE (16))
+ } OPTIONAL, -- Cond TM
+ ue-TransmitAntennaSelection CHOICE{
+ release NULL,
+ setup ENUMERATED {closedLoop, openLoop}
+ }
+}
+
+AntennaInfoDedicated-v920 ::= SEQUENCE {
+ codebookSubsetRestriction-v920 CHOICE {
+ n2TxAntenna-tm8-r9 BIT STRING (SIZE (6)),
+ n4TxAntenna-tm8-r9 BIT STRING (SIZE (32))
+ } OPTIONAL -- Cond TM8
+}
+
+
+CQI-ReportConfig ::= SEQUENCE {
+ cqi-ReportModeAperiodic ENUMERATED {
+ rm12, rm20, rm22, rm30, rm31,
+ spare3, spare2, spare1} OPTIONAL, -- Need OR
+ nomPDSCH-RS-EPRE-Offset INTEGER (-1..6),
+ cqi-ReportPeriodic CQI-ReportPeriodic OPTIONAL -- Need ON
+}
+
+CQI-ReportConfig-v920 ::= SEQUENCE {
+ cqi-Mask-r9 ENUMERATED {setup} OPTIONAL, -- Cond cqi-Setup
+ pmi-RI-Report-r9 ENUMERATED {setup} OPTIONAL -- Cond PMIRI
+}
+
+CQI-ReportPeriodic ::= CHOICE {
+ release NULL,
+ setup SEQUENCE {
+ cqi-PUCCH-ResourceIndex INTEGER (0.. 1185),
+ cqi-pmi-ConfigIndex INTEGER (0..1023),
+ cqi-FormatIndicatorPeriodic CHOICE {
+ widebandCQI NULL,
+ subbandCQI SEQUENCE {
+ k INTEGER (1..4)
+ }
+ },
+ ri-ConfigIndex INTEGER (0..1023) OPTIONAL, -- Need OR
+ simultaneousAckNackAndCQI BOOLEAN
+ }
+}
+
+
+DRB-Identity ::= INTEGER (1..32)
+
+
+LogicalChannelConfig ::= SEQUENCE {
+ ul-SpecificParameters SEQUENCE {
+ priority INTEGER (1..16),
+ prioritisedBitRate ENUMERATED {
+ kBps0, kBps8, kBps16, kBps32, kBps64, kBps128,
+ kBps256, infinity, spare8, spare7, spare6,
+ spare5, spare4, spare3, spare2, spare1},
+ bucketSizeDuration ENUMERATED {
+ ms50, ms100, ms150, ms300, ms500, ms1000, spare2,
+ spare1},
+ logicalChannelGroup INTEGER (0..3) OPTIONAL -- Need OR
+ } OPTIONAL, -- Cond UL
+ ...,
+ [[ logicalChannelSR-Mask-r9 ENUMERATED {setup} OPTIONAL -- Cond SRmask
+ ]]
+}
+
+
+MAC-MainConfig ::= SEQUENCE {
+ ul-SCH-Config SEQUENCE {
+ maxHARQ-Tx ENUMERATED {
+ n1, n2, n3, n4, n5, n6, n7, n8,
+ n10, n12, n16, n20, n24, n28,
+ spare2, spare1} OPTIONAL, -- Need ON
+ periodicBSR-Timer ENUMERATED {
+ sf5, sf10, sf16, sf20, sf32, sf40, sf64, sf80,
+ sf128, sf160, sf320, sf640, sf1280, sf2560,
+ infinity, spare1} OPTIONAL, -- Need ON
+ retxBSR-Timer ENUMERATED {
+ sf320, sf640, sf1280, sf2560, sf5120,
+ sf10240, spare2, spare1},
+ ttiBundling BOOLEAN
+ } OPTIONAL, -- Need ON
+ drx-Config DRX-Config OPTIONAL, -- Need ON
+ timeAlignmentTimerDedicated TimeAlignmentTimer,
+ phr-Config CHOICE {
+ release NULL,
+ setup SEQUENCE {
+ periodicPHR-Timer ENUMERATED {sf10, sf20, sf50, sf100, sf200,
+ sf500, sf1000, infinity},
+ prohibitPHR-Timer ENUMERATED {sf0, sf10, sf20, sf50, sf100,
+ sf200, sf500, sf1000},
+ dl-PathlossChange ENUMERATED {dB1, dB3, dB6, infinity}
+ }
+ } OPTIONAL, -- Need ON
+ ...,
+ [[ sr-ProhibitTimer-r9 INTEGER (0..7) OPTIONAL -- Need ON
+ ]]
+}
+
+DRX-Config ::= CHOICE {
+ release NULL,
+ setup SEQUENCE {
+ onDurationTimer ENUMERATED {
+ psf1, psf2, psf3, psf4, psf5, psf6,
+ psf8, psf10, psf20, psf30, psf40,
+ psf50, psf60, psf80, psf100,
+ psf200},
+ drx-InactivityTimer ENUMERATED {
+ psf1, psf2, psf3, psf4, psf5, psf6,
+ psf8, psf10, psf20, psf30, psf40,
+ psf50, psf60, psf80, psf100,
+ psf200, psf300, psf500, psf750,
+ psf1280, psf1920, psf2560, spare10,
+ spare9, spare8, spare7, spare6,
+ spare5, spare4, spare3, spare2,
+ spare1},
+ drx-RetransmissionTimer ENUMERATED {
+ psf1, psf2, psf4, psf6, psf8, psf16,
+ psf24, psf33},
+ longDRX-CycleStartOffset CHOICE {
+ sf10 INTEGER(0..9),
+ sf20 INTEGER(0..19),
+ sf32 INTEGER(0..31),
+ sf40 INTEGER(0..39),
+ sf64 INTEGER(0..63),
+ sf80 INTEGER(0..79),
+ sf128 INTEGER(0..127),
+ sf160 INTEGER(0..159),
+ sf256 INTEGER(0..255),
+ sf320 INTEGER(0..319),
+ sf512 INTEGER(0..511),
+ sf640 INTEGER(0..639),
+ sf1024 INTEGER(0..1023),
+ sf1280 INTEGER(0..1279),
+ sf2048 INTEGER(0..2047),
+ sf2560 INTEGER(0..2559)
+ },
+ shortDRX SEQUENCE {
+ shortDRX-Cycle ENUMERATED {
+ sf2, sf5, sf8, sf10, sf16, sf20,
+ sf32, sf40, sf64, sf80, sf128, sf160,
+ sf256, sf320, sf512, sf640},
+ drxShortCycleTimer INTEGER (1..16)
+ } OPTIONAL -- Need OR
+ }
+}
+
+
+PDCP-Config ::= SEQUENCE {
+ discardTimer ENUMERATED {
+ ms50, ms100, ms150, ms300, ms500,
+ ms750, ms1500, infinity
+ } OPTIONAL, -- Cond Setup
+ rlc-AM SEQUENCE {
+ statusReportRequired BOOLEAN
+ } OPTIONAL, -- Cond Rlc-AM
+ rlc-UM SEQUENCE {
+ pdcp-SN-Size ENUMERATED {len7bits, len12bits}
+ } OPTIONAL, -- Cond Rlc-UM
+ headerCompression CHOICE {
+ notUsed NULL,
+ rohc SEQUENCE {
+ maxCID INTEGER (1..16383) DEFAULT 15,
+ profiles SEQUENCE {
+ profile0x0001 BOOLEAN,
+ profile0x0002 BOOLEAN,
+ profile0x0003 BOOLEAN,
+ profile0x0004 BOOLEAN,
+ profile0x0006 BOOLEAN,
+ profile0x0101 BOOLEAN,
+ profile0x0102 BOOLEAN,
+ profile0x0103 BOOLEAN,
+ profile0x0104 BOOLEAN
+ },
+ ...
+ }
+ },
+ ...
+}
+
+
+PDSCH-ConfigCommon ::= SEQUENCE {
+ referenceSignalPower INTEGER (-60..50),
+ p-b INTEGER (0..3)
+}
+
+PDSCH-ConfigDedicated::= SEQUENCE {
+ p-a ENUMERATED {
+ dB-6, dB-4dot77, dB-3, dB-1dot77,
+ dB0, dB1, dB2, dB3}
+}
+
+
+PHICH-Config ::= SEQUENCE {
+ phich-Duration ENUMERATED {normal, extended},
+ phich-Resource ENUMERATED {oneSixth, half, one, two}
+}
+
+
+PhysicalConfigDedicated ::= SEQUENCE {
+ pdsch-ConfigDedicated PDSCH-ConfigDedicated OPTIONAL, -- Need ON
+ pucch-ConfigDedicated PUCCH-ConfigDedicated OPTIONAL, -- Need ON
+ pusch-ConfigDedicated PUSCH-ConfigDedicated OPTIONAL, -- Need ON
+ uplinkPowerControlDedicated UplinkPowerControlDedicated OPTIONAL, -- Need ON
+ tpc-PDCCH-ConfigPUCCH TPC-PDCCH-Config OPTIONAL, -- Need ON
+ tpc-PDCCH-ConfigPUSCH TPC-PDCCH-Config OPTIONAL, -- Need ON
+ cqi-ReportConfig CQI-ReportConfig OPTIONAL, -- Need ON
+ soundingRS-UL-ConfigDedicated SoundingRS-UL-ConfigDedicated OPTIONAL, -- Need ON
+ antennaInfo CHOICE {
+ explicitValue AntennaInfoDedicated,
+ defaultValue NULL
+ } OPTIONAL, -- Need ON
+ schedulingRequestConfig SchedulingRequestConfig OPTIONAL, -- Need ON
+ ...,
+ [[ cqi-ReportConfig-v920 CQI-ReportConfig-v920 OPTIONAL, -- Need ON
+ antennaInfo-v920 AntennaInfoDedicated-v920 OPTIONAL -- Need ON
+ ]]
+}
+
+
+P-Max ::= INTEGER (-30..33)
+
+
+PRACH-ConfigSIB ::= SEQUENCE {
+ rootSequenceIndex INTEGER (0..837),
+ prach-ConfigInfo PRACH-ConfigInfo
+}
+
+PRACH-Config ::= SEQUENCE {
+ rootSequenceIndex INTEGER (0..837),
+ prach-ConfigInfo PRACH-ConfigInfo OPTIONAL -- Need ON
+}
+
+PRACH-ConfigInfo ::= SEQUENCE {
+ prach-ConfigIndex INTEGER (0..63),
+ highSpeedFlag BOOLEAN,
+ zeroCorrelationZoneConfig INTEGER (0..15),
+ prach-FreqOffset INTEGER (0..94)
+}
+
+
+PresenceAntennaPort1 ::= BOOLEAN
+
+
+PUCCH-ConfigCommon ::= SEQUENCE {
+ deltaPUCCH-Shift ENUMERATED {ds1, ds2, ds3},
+ nRB-CQI INTEGER (0..98),
+ nCS-AN INTEGER (0..7),
+ n1PUCCH-AN INTEGER (0..2047)
+}
+
+PUCCH-ConfigDedicated ::= SEQUENCE {
+ ackNackRepetition CHOICE{
+ release NULL,
+ setup SEQUENCE {
+ repetitionFactor ENUMERATED {n2, n4, n6, spare1},
+ n1PUCCH-AN-Rep INTEGER (0..2047)
+ }
+ },
+ tdd-AckNackFeedbackMode ENUMERATED {bundling, multiplexing} OPTIONAL -- Cond TDD
+}
+
+
+PUSCH-ConfigCommon ::= SEQUENCE {
+ pusch-ConfigBasic SEQUENCE {
+ n-SB INTEGER (1..4),
+ hoppingMode ENUMERATED {interSubFrame, intraAndInterSubFrame},
+ pusch-HoppingOffset INTEGER (0..98),
+ enable64QAM BOOLEAN
+ },
+ ul-ReferenceSignalsPUSCH UL-ReferenceSignalsPUSCH
+}
+
+PUSCH-ConfigDedicated ::= SEQUENCE {
+ betaOffset-ACK-Index INTEGER (0..15),
+ betaOffset-RI-Index INTEGER (0..15),
+ betaOffset-CQI-Index INTEGER (0..15)
+}
+
+UL-ReferenceSignalsPUSCH ::= SEQUENCE {
+ groupHoppingEnabled BOOLEAN,
+ groupAssignmentPUSCH INTEGER (0..29),
+ sequenceHoppingEnabled BOOLEAN,
+ cyclicShift INTEGER (0..7)
+}
+
+
+RACH-ConfigCommon ::= SEQUENCE {
+ preambleInfo SEQUENCE {
+ numberOfRA-Preambles ENUMERATED {
+ n4, n8, n12, n16 ,n20, n24, n28,
+ n32, n36, n40, n44, n48, n52, n56,
+ n60, n64},
+ preamblesGroupAConfig SEQUENCE {
+ sizeOfRA-PreamblesGroupA ENUMERATED {
+ n4, n8, n12, n16 ,n20, n24, n28,
+ n32, n36, n40, n44, n48, n52, n56,
+ n60},
+ messageSizeGroupA ENUMERATED {b56, b144, b208, b256},
+ messagePowerOffsetGroupB ENUMERATED {
+ minusinfinity, dB0, dB5, dB8, dB10, dB12,
+ dB15, dB18},
+ ...
+ } OPTIONAL -- Need OP
+ },
+ powerRampingParameters SEQUENCE {
+ powerRampingStep ENUMERATED {dB0, dB2,dB4, dB6},
+ preambleInitialReceivedTargetPower ENUMERATED {
+ dBm-120, dBm-118, dBm-116, dBm-114, dBm-112,
+ dBm-110, dBm-108, dBm-106, dBm-104, dBm-102,
+ dBm-100, dBm-98, dBm-96, dBm-94,
+ dBm-92, dBm-90}
+ },
+ ra-SupervisionInfo SEQUENCE {
+ preambleTransMax ENUMERATED {
+ n3, n4, n5, n6, n7, n8, n10, n20, n50,
+ n100, n200},
+ ra-ResponseWindowSize ENUMERATED {
+ sf2, sf3, sf4, sf5, sf6, sf7,
+ sf8, sf10},
+ mac-ContentionResolutionTimer ENUMERATED {
+ sf8, sf16, sf24, sf32, sf40, sf48,
+ sf56, sf64}
+ },
+ maxHARQ-Msg3Tx INTEGER (1..8),
+ ...
+}
+
+
+RACH-ConfigDedicated ::= SEQUENCE {
+ ra-PreambleIndex INTEGER (0..63),
+ ra-PRACH-MaskIndex INTEGER (0..15)
+}
+
+
+RadioResourceConfigCommonSIB ::= SEQUENCE {
+ rach-ConfigCommon RACH-ConfigCommon,
+ bcch-Config BCCH-Config,
+ pcch-Config PCCH-Config,
+ prach-Config PRACH-ConfigSIB,
+ pdsch-ConfigCommon PDSCH-ConfigCommon,
+ pusch-ConfigCommon PUSCH-ConfigCommon,
+ pucch-ConfigCommon PUCCH-ConfigCommon,
+ soundingRS-UL-ConfigCommon SoundingRS-UL-ConfigCommon,
+ uplinkPowerControlCommon UplinkPowerControlCommon,
+ ul-CyclicPrefixLength UL-CyclicPrefixLength,
+ ...
+}
+
+RadioResourceConfigCommon ::= SEQUENCE {
+ rach-ConfigCommon RACH-ConfigCommon OPTIONAL, -- Need ON
+ prach-Config PRACH-Config,
+ pdsch-ConfigCommon PDSCH-ConfigCommon OPTIONAL, -- Need ON
+ pusch-ConfigCommon PUSCH-ConfigCommon,
+ phich-Config PHICH-Config OPTIONAL, -- Need ON
+ pucch-ConfigCommon PUCCH-ConfigCommon OPTIONAL, -- Need ON
+ soundingRS-UL-ConfigCommon SoundingRS-UL-ConfigCommon OPTIONAL, -- Need ON
+ uplinkPowerControlCommon UplinkPowerControlCommon OPTIONAL, -- Need ON
+ antennaInfoCommon AntennaInfoCommon OPTIONAL, -- Need ON
+ p-Max P-Max OPTIONAL, -- Need OP
+ tdd-Config TDD-Config OPTIONAL, -- Cond TDD
+ ul-CyclicPrefixLength UL-CyclicPrefixLength,
+ ...
+}
+
+BCCH-Config ::= SEQUENCE {
+ modificationPeriodCoeff ENUMERATED {n2, n4, n8, n16}
+}
+
+PCCH-Config ::= SEQUENCE {
+ defaultPagingCycle ENUMERATED {
+ rf32, rf64, rf128, rf256},
+ nB ENUMERATED {
+ fourT, twoT, oneT, halfT, quarterT, oneEighthT,
+ oneSixteenthT, oneThirtySecondT}
+}
+
+UL-CyclicPrefixLength ::= ENUMERATED {len1, len2}
+
+
+RadioResourceConfigDedicated ::= SEQUENCE {
+ srb-ToAddModList SRB-ToAddModList OPTIONAL, -- Cond HO-Conn
+ drb-ToAddModList DRB-ToAddModList OPTIONAL, -- Cond HO-toEUTRA
+ drb-ToReleaseList DRB-ToReleaseList OPTIONAL, -- Need ON
+ mac-MainConfig CHOICE {
+ explicitValue MAC-MainConfig,
+ defaultValue NULL
+ } OPTIONAL, -- Cond HO-toEUTRA2
+ sps-Config SPS-Config OPTIONAL, -- Need ON
+ physicalConfigDedicated PhysicalConfigDedicated OPTIONAL, -- Need ON
+ ...,
+ [[ rlf-TimersAndConstants-r9 RLF-TimersAndConstants-r9 OPTIONAL -- Need ON
+ ]]
+}
+
+SRB-ToAddModList ::= SEQUENCE (SIZE (1..2)) OF SRB-ToAddMod
+
+SRB-ToAddMod ::= SEQUENCE {
+ srb-Identity INTEGER (1..2),
+ rlc-Config CHOICE {
+ explicitValue RLC-Config,
+ defaultValue NULL
+ } OPTIONAL, -- Cond Setup
+ logicalChannelConfig CHOICE {
+ explicitValue LogicalChannelConfig,
+ defaultValue NULL
+ } OPTIONAL, -- Cond Setup
+ ...
+}
+
+DRB-ToAddModList ::= SEQUENCE (SIZE (1..maxDRB)) OF DRB-ToAddMod
+
+DRB-ToAddMod ::= SEQUENCE {
+ eps-BearerIdentity INTEGER (0..15) OPTIONAL, -- Cond DRB-Setup
+ drb-Identity DRB-Identity,
+ pdcp-Config PDCP-Config OPTIONAL, -- Cond PDCP
+ rlc-Config RLC-Config OPTIONAL, -- Cond Setup
+ logicalChannelIdentity INTEGER (3..10) OPTIONAL, -- Cond DRB-Setup
+ logicalChannelConfig LogicalChannelConfig OPTIONAL, -- Cond Setup
+ ...
+}
+
+DRB-ToReleaseList ::= SEQUENCE (SIZE (1..maxDRB)) OF DRB-Identity
+
+
+RLC-Config ::= CHOICE {
+ am SEQUENCE {
+ ul-AM-RLC UL-AM-RLC,
+ dl-AM-RLC DL-AM-RLC
+ },
+ um-Bi-Directional SEQUENCE {
+ ul-UM-RLC UL-UM-RLC,
+ dl-UM-RLC DL-UM-RLC
+ },
+ um-Uni-Directional-UL SEQUENCE {
+ ul-UM-RLC UL-UM-RLC
+ },
+ um-Uni-Directional-DL SEQUENCE {
+ dl-UM-RLC DL-UM-RLC
+ },
+ ...
+}
+
+UL-AM-RLC ::= SEQUENCE {
+ t-PollRetransmit T-PollRetransmit,
+ pollPDU PollPDU,
+ pollByte PollByte,
+ maxRetxThreshold ENUMERATED {
+ t1, t2, t3, t4, t6, t8, t16, t32}
+}
+
+DL-AM-RLC ::= SEQUENCE {
+ t-Reordering T-Reordering,
+ t-StatusProhibit T-StatusProhibit
+}
+
+UL-UM-RLC ::= SEQUENCE {
+ sn-FieldLength SN-FieldLength
+}
+
+DL-UM-RLC ::= SEQUENCE {
+ sn-FieldLength SN-FieldLength,
+ t-Reordering T-Reordering
+}
+
+SN-FieldLength ::= ENUMERATED {size5, size10}
+
+T-PollRetransmit ::= ENUMERATED {
+ ms5, ms10, ms15, ms20, ms25, ms30, ms35,
+ ms40, ms45, ms50, ms55, ms60, ms65, ms70,
+ ms75, ms80, ms85, ms90, ms95, ms100, ms105,
+ ms110, ms115, ms120, ms125, ms130, ms135,
+ ms140, ms145, ms150, ms155, ms160, ms165,
+ ms170, ms175, ms180, ms185, ms190, ms195,
+ ms200, ms205, ms210, ms215, ms220, ms225,
+ ms230, ms235, ms240, ms245, ms250, ms300,
+ ms350, ms400, ms450, ms500, spare9, spare8,
+ spare7, spare6, spare5, spare4, spare3,
+ spare2, spare1}
+
+PollPDU ::= ENUMERATED {
+ p4, p8, p16, p32, p64, p128, p256, pInfinity}
+
+PollByte ::= ENUMERATED {
+ kB25, kB50, kB75, kB100, kB125, kB250, kB375,
+ kB500, kB750, kB1000, kB1250, kB1500, kB2000,
+ kB3000, kBinfinity, spare1}
+
+T-Reordering ::= ENUMERATED {
+ ms0, ms5, ms10, ms15, ms20, ms25, ms30, ms35,
+ ms40, ms45, ms50, ms55, ms60, ms65, ms70,
+ ms75, ms80, ms85, ms90, ms95, ms100, ms110,
+ ms120, ms130, ms140, ms150, ms160, ms170,
+ ms180, ms190, ms200, spare1}
+
+T-StatusProhibit ::= ENUMERATED {
+ ms0, ms5, ms10, ms15, ms20, ms25, ms30, ms35,
+ ms40, ms45, ms50, ms55, ms60, ms65, ms70,
+ ms75, ms80, ms85, ms90, ms95, ms100, ms105,
+ ms110, ms115, ms120, ms125, ms130, ms135,
+ ms140, ms145, ms150, ms155, ms160, ms165,
+ ms170, ms175, ms180, ms185, ms190, ms195,
+ ms200, ms205, ms210, ms215, ms220, ms225,
+ ms230, ms235, ms240, ms245, ms250, ms300,
+ ms350, ms400, ms450, ms500, spare8, spare7,
+ spare6, spare5, spare4, spare3, spare2,
+ spare1}
+
+
+RLF-TimersAndConstants-r9 ::= CHOICE {
+ release NULL,
+ setup SEQUENCE {
+ t301-r9 ENUMERATED {
+ ms100, ms200, ms300, ms400, ms600, ms1000, ms1500,
+ ms2000},
+ t310-r9 ENUMERATED {
+ ms0, ms50, ms100, ms200, ms500, ms1000, ms2000},
+ n310-r9 ENUMERATED {
+ n1, n2, n3, n4, n6, n8, n10, n20},
+ t311-r9 ENUMERATED {
+ ms1000, ms3000, ms5000, ms10000, ms15000,
+ ms20000, ms30000},
+ n311-r9 ENUMERATED {
+ n1, n2, n3, n4, n5, n6, n8, n10},
+ ...
+ }
+}
+
+
+SchedulingRequestConfig ::= CHOICE {
+ release NULL,
+ setup SEQUENCE {
+ sr-PUCCH-ResourceIndex INTEGER (0..2047),
+ sr-ConfigIndex INTEGER (0..157),
+ dsr-TransMax ENUMERATED {
+ n4, n8, n16, n32, n64, spare3, spare2, spare1}
+ }
+}
+
+
+SoundingRS-UL-ConfigCommon ::= CHOICE {
+ release NULL,
+ setup SEQUENCE {
+ srs-BandwidthConfig ENUMERATED {bw0, bw1, bw2, bw3, bw4, bw5, bw6, bw7},
+ srs-SubframeConfig ENUMERATED {
+ sc0, sc1, sc2, sc3, sc4, sc5, sc6, sc7,
+ sc8, sc9, sc10, sc11, sc12, sc13, sc14, sc15},
+ ackNackSRS-SimultaneousTransmission BOOLEAN,
+ srs-MaxUpPts ENUMERATED {true} OPTIONAL -- Cond TDD
+ }
+}
+
+SoundingRS-UL-ConfigDedicated ::= CHOICE{
+ release NULL,
+ setup SEQUENCE {
+ srs-Bandwidth ENUMERATED {bw0, bw1, bw2, bw3},
+ srs-HoppingBandwidth ENUMERATED {hbw0, hbw1, hbw2, hbw3},
+ freqDomainPosition INTEGER (0..23),
+ duration BOOLEAN,
+ srs-ConfigIndex INTEGER (0..1023),
+ transmissionComb INTEGER (0..1),
+ cyclicShift ENUMERATED {cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7}
+ }
+}
+
+
+
+SPS-Config ::= SEQUENCE {
+ semiPersistSchedC-RNTI C-RNTI OPTIONAL, -- Need OR
+ sps-ConfigDL SPS-ConfigDL OPTIONAL, -- Need ON
+ sps-ConfigUL SPS-ConfigUL OPTIONAL -- Need ON
+}
+
+SPS-ConfigDL ::= CHOICE{
+ release NULL,
+ setup SEQUENCE {
+ semiPersistSchedIntervalDL ENUMERATED {
+ sf10, sf20, sf32, sf40, sf64, sf80,
+ sf128, sf160, sf320, sf640, spare6,
+ spare5, spare4, spare3, spare2,
+ spare1},
+ numberOfConfSPS-Processes INTEGER (1..8),
+ n1-PUCCH-AN-PersistentList N1-PUCCH-AN-PersistentList,
+ ...
+ }
+}
+
+SPS-ConfigUL ::= CHOICE {
+ release NULL,
+ setup SEQUENCE {
+ semiPersistSchedIntervalUL ENUMERATED {
+ sf10, sf20, sf32, sf40, sf64, sf80,
+ sf128, sf160, sf320, sf640, spare6,
+ spare5, spare4, spare3, spare2,
+ spare1},
+ implicitReleaseAfter ENUMERATED {e2, e3, e4, e8},
+ p0-Persistent SEQUENCE {
+ p0-NominalPUSCH-Persistent INTEGER (-126..24),
+ p0-UE-PUSCH-Persistent INTEGER (-8..7)
+ } OPTIONAL, -- Need OP
+ twoIntervalsConfig ENUMERATED {true} OPTIONAL, -- Cond TDD
+ ...
+ }
+}
+
+N1-PUCCH-AN-PersistentList ::= SEQUENCE (SIZE (1..4)) OF INTEGER (0..2047)
+
+
+TDD-Config ::= SEQUENCE {
+ subframeAssignment ENUMERATED {
+ sa0, sa1, sa2, sa3, sa4, sa5, sa6},
+ specialSubframePatterns ENUMERATED {
+ ssp0, ssp1, ssp2, ssp3, ssp4,ssp5, ssp6, ssp7,
+ ssp8}
+}
+
+
+TimeAlignmentTimer ::= ENUMERATED {
+ sf500, sf750, sf1280, sf1920, sf2560, sf5120,
+ sf10240, infinity}
+
+TPC-PDCCH-Config ::= CHOICE {
+ release NULL,
+ setup SEQUENCE {
+ tpc-RNTI BIT STRING (SIZE (16)),
+ tpc-Index TPC-Index
+ }
+}
+
+TPC-Index ::= CHOICE {
+ indexOfFormat3 INTEGER (1..15),
+ indexOfFormat3A INTEGER (1..31)
+}
+
+
+UplinkPowerControlCommon ::= SEQUENCE {
+ p0-NominalPUSCH INTEGER (-126..24),
+ alpha ENUMERATED {al0, al04, al05, al06, al07, al08, al09, al1},
+ p0-NominalPUCCH INTEGER (-127..-96),
+ deltaFList-PUCCH DeltaFList-PUCCH,
+ deltaPreambleMsg3 INTEGER (-1..6)
+}
+
+UplinkPowerControlDedicated ::= SEQUENCE {
+ p0-UE-PUSCH INTEGER (-8..7),
+ deltaMCS-Enabled ENUMERATED {en0, en1},
+ accumulationEnabled BOOLEAN,
+ p0-UE-PUCCH INTEGER (-8..7),
+ pSRS-Offset INTEGER (0..15),
+ filterCoefficient FilterCoefficient DEFAULT fc4
+}
+
+DeltaFList-PUCCH ::= SEQUENCE {
+ deltaF-PUCCH-Format1 ENUMERATED {deltaF-2, deltaF0, deltaF2},
+ deltaF-PUCCH-Format1b ENUMERATED {deltaF1, deltaF3, deltaF5},
+ deltaF-PUCCH-Format2 ENUMERATED {deltaF-2, deltaF0, deltaF1, deltaF2},
+ deltaF-PUCCH-Format2a ENUMERATED {deltaF-2, deltaF0, deltaF2},
+ deltaF-PUCCH-Format2b ENUMERATED {deltaF-2, deltaF0, deltaF2}
+}
+
+
+NextHopChainingCount ::= INTEGER (0..7)
+
+
+SecurityAlgorithmConfig ::= SEQUENCE {
+ cipheringAlgorithm ENUMERATED {
+ eea0, eea1, eea2, spare5, spare4, spare3,
+ spare2, spare1, ...},
+ integrityProtAlgorithm ENUMERATED {
+ eia0-v920, eia1, eia2, spare5, spare4, spare3,
+ spare2, spare1, ...}
+}
+
+
+ShortMAC-I ::= BIT STRING (SIZE (16))
+
+
+AdditionalSpectrumEmission ::= INTEGER (1..32)
+
+
+ARFCN-ValueCDMA2000 ::= INTEGER (0..2047)
+
+
+ARFCN-ValueEUTRA ::= INTEGER (0..maxEARFCN)
+
+
+ARFCN-ValueGERAN ::= INTEGER (0..1023)
+
+
+ARFCN-ValueUTRA ::= INTEGER (0..16383)
+
+
+BandclassCDMA2000 ::= ENUMERATED {
+ bc0, bc1, bc2, bc3, bc4, bc5, bc6, bc7, bc8,
+ bc9, bc10, bc11, bc12, bc13, bc14, bc15, bc16,
+ bc17, spare14, spare13, spare12, spare11, spare10,
+ spare9, spare8, spare7, spare6, spare5, spare4,
+ spare3, spare2, spare1, ...}
+
+
+BandIndicatorGERAN ::= ENUMERATED {dcs1800, pcs1900}
+
+
+CarrierFreqCDMA2000 ::= SEQUENCE {
+ bandClass BandclassCDMA2000,
+ arfcn ARFCN-ValueCDMA2000
+}
+
+
+CarrierFreqGERAN ::= SEQUENCE {
+ arfcn ARFCN-ValueGERAN,
+ bandIndicator BandIndicatorGERAN
+}
+
+
+CarrierFreqsGERAN ::= SEQUENCE {
+ startingARFCN ARFCN-ValueGERAN,
+ bandIndicator BandIndicatorGERAN,
+ followingARFCNs CHOICE {
+ explicitListOfARFCNs ExplicitListOfARFCNs,
+ equallySpacedARFCNs SEQUENCE {
+ arfcn-Spacing INTEGER (1..8),
+ numberOfFollowingARFCNs INTEGER (0..31)
+ },
+ variableBitMapOfARFCNs OCTET STRING (SIZE (1..16))
+ }
+}
+
+ExplicitListOfARFCNs ::= SEQUENCE (SIZE (0..31)) OF ARFCN-ValueGERAN
+
+
+CDMA2000-Type ::= ENUMERATED {type1XRTT, typeHRPD}
+
+
+CellIdentity ::= BIT STRING (SIZE (28))
+
+
+CellIndexList ::= SEQUENCE (SIZE (1..maxCellMeas)) OF CellIndex
+
+CellIndex ::= INTEGER (1..maxCellMeas)
+
+
+CellReselectionPriority ::= INTEGER (0..7)
+
+
+CSFB-RegistrationParam1XRTT ::= SEQUENCE {
+ sid BIT STRING (SIZE (15)),
+ nid BIT STRING (SIZE (16)),
+ multipleSID BOOLEAN,
+ multipleNID BOOLEAN,
+ homeReg BOOLEAN,
+ foreignSIDReg BOOLEAN,
+ foreignNIDReg BOOLEAN,
+ parameterReg BOOLEAN,
+ powerUpReg BOOLEAN,
+ registrationPeriod BIT STRING (SIZE (7)),
+ registrationZone BIT STRING (SIZE (12)),
+ totalZone BIT STRING (SIZE (3)),
+ zoneTimer BIT STRING (SIZE (3))
+}
+
+CSFB-RegistrationParam1XRTT-v920 ::= SEQUENCE {
+ powerDownReg-r9 ENUMERATED {true}
+}
+
+
+CellGlobalIdEUTRA ::= SEQUENCE {
+ plmn-Identity PLMN-Identity,
+ cellIdentity CellIdentity
+}
+
+
+CellGlobalIdUTRA ::= SEQUENCE {
+ plmn-Identity PLMN-Identity,
+ cellIdentity BIT STRING (SIZE (28))
+}
+
+
+CellGlobalIdGERAN ::= SEQUENCE {
+ plmn-Identity PLMN-Identity,
+ locationAreaCode BIT STRING (SIZE (16)),
+ cellIdentity BIT STRING (SIZE (16))
+}
+
+
+CellGlobalIdCDMA2000 ::= CHOICE {
+ cellGlobalId1XRTT BIT STRING (SIZE (47)),
+ cellGlobalIdHRPD BIT STRING (SIZE (128))
+}
+
+
+CSG-Identity ::= BIT STRING (SIZE (27))
+
+
+MobilityControlInfo ::= SEQUENCE {
+ targetPhysCellId PhysCellId,
+ carrierFreq CarrierFreqEUTRA OPTIONAL, -- Cond HO-toEUTRA
+ carrierBandwidth CarrierBandwidthEUTRA OPTIONAL, -- Cond HO-toEUTRA
+ additionalSpectrumEmission AdditionalSpectrumEmission OPTIONAL, -- Cond HO-toEUTRA
+ t304 ENUMERATED {
+ ms50, ms100, ms150, ms200, ms500, ms1000,
+ ms2000, spare1},
+ newUE-Identity C-RNTI,
+ radioResourceConfigCommon RadioResourceConfigCommon,
+ rach-ConfigDedicated RACH-ConfigDedicated OPTIONAL, -- Need OP
+ ...
+}
+
+CarrierBandwidthEUTRA ::= SEQUENCE {
+ dl-Bandwidth ENUMERATED {
+ n6, n15, n25, n50, n75, n100, spare10,
+ spare9, spare8, spare7, spare6, spare5,
+ spare4, spare3, spare2, spare1},
+ ul-Bandwidth ENUMERATED {
+ n6, n15, n25, n50, n75, n100, spare10,
+ spare9, spare8, spare7, spare6, spare5,
+ spare4, spare3, spare2, spare1} OPTIONAL -- Need OP
+}
+
+CarrierFreqEUTRA ::= SEQUENCE {
+ dl-CarrierFreq ARFCN-ValueEUTRA,
+ ul-CarrierFreq ARFCN-ValueEUTRA OPTIONAL -- Cond FDD
+}
+
+
+MobilityParametersCDMA2000 ::= OCTET STRING
+
+
+MobilityStateParameters ::= SEQUENCE {
+ t-Evaluation ENUMERATED {
+ s30, s60, s120, s180, s240, spare3, spare2, spare1},
+ t-HystNormal ENUMERATED {
+ s30, s60, s120, s180, s240, spare3, spare2, spare1},
+ n-CellChangeMedium INTEGER (1..16),
+ n-CellChangeHigh INTEGER (1..16)
+}
+
+
+PhysCellId ::= INTEGER (0..503)
+
+
+PhysCellIdRange ::= SEQUENCE {
+ start PhysCellId,
+ range ENUMERATED {
+ n4, n8, n12, n16, n24, n32, n48, n64, n84,
+ n96, n128, n168, n252, n504, spare2,
+ spare1} OPTIONAL -- Need OP
+}
+
+
+PhysCellIdCDMA2000 ::= INTEGER (0..maxPNOffset)
+
+
+PhysCellIdGERAN ::= SEQUENCE {
+ networkColourCode BIT STRING (SIZE (3)),
+ baseStationColourCode BIT STRING (SIZE (3))
+}
+
+
+PhysCellIdUTRA-FDD ::= INTEGER (0..511)
+
+
+PhysCellIdUTRA-TDD ::= INTEGER (0..127)
+
+
+PLMN-Identity ::= SEQUENCE {
+ mcc MCC OPTIONAL, -- Cond MCC
+ mnc MNC
+}
+
+MCC ::= SEQUENCE (SIZE (3)) OF
+ MCC-MNC-Digit
+
+MNC ::= SEQUENCE (SIZE (2..3)) OF
+ MCC-MNC-Digit
+
+MCC-MNC-Digit ::= INTEGER (0..9)
+
+
+
+PreRegistrationInfoHRPD ::= SEQUENCE {
+ preRegistrationAllowed BOOLEAN,
+ preRegistrationZoneId PreRegistrationZoneIdHRPD OPTIONAL, -- cond PreRegAllowed
+ secondaryPreRegistrationZoneIdList SecondaryPreRegistrationZoneIdListHRPD OPTIONAL -- Need OR
+}
+
+SecondaryPreRegistrationZoneIdListHRPD ::= SEQUENCE (SIZE (1..2)) OF PreRegistrationZoneIdHRPD
+
+PreRegistrationZoneIdHRPD ::= INTEGER (0..255)
+
+
+Q-QualMin-r9 ::= INTEGER (-34..-3)
+
+
+Q-RxLevMin ::= INTEGER (-70..-22)
+
+
+Q-OffsetRange ::= ENUMERATED {
+ dB-24, dB-22, dB-20, dB-18, dB-16, dB-14,
+ dB-12, dB-10, dB-8, dB-6, dB-5, dB-4, dB-3,
+ dB-2, dB-1, dB0, dB1, dB2, dB3, dB4, dB5,
+ dB6, dB8, dB10, dB12, dB14, dB16, dB18,
+ dB20, dB22, dB24}
+
+
+Q-OffsetRangeInterRAT ::= INTEGER (-15..15)
+
+
+ReselectionThreshold ::= INTEGER (0..31)
+
+
+ReselectionThresholdQ-r9 ::= INTEGER (0..31)
+
+
+SpeedStateScaleFactors ::= SEQUENCE {
+ sf-Medium ENUMERATED {oDot25, oDot5, oDot75, lDot0},
+ sf-High ENUMERATED {oDot25, oDot5, oDot75, lDot0}
+}
+
+SystemInfoListGERAN ::= SEQUENCE (SIZE (1..maxGERAN-SI)) OF
+ OCTET STRING (SIZE (1..23))
+
+
+SystemTimeInfoCDMA2000 ::= SEQUENCE {
+ cdma-EUTRA-Synchronisation BOOLEAN,
+ cdma-SystemTime CHOICE {
+ synchronousSystemTime BIT STRING (SIZE (39)),
+ asynchronousSystemTime BIT STRING (SIZE (49))
+ }
+}
+
+
+TrackingAreaCode ::= BIT STRING (SIZE (16))
+
+
+T-Reselection ::= INTEGER (0..7)
+
+
+AllowedMeasBandwidth ::= ENUMERATED {mbw6, mbw15, mbw25, mbw50, mbw75, mbw100}
+
+
+Hysteresis ::= INTEGER (0..30)
+
+
+MeasConfig ::= SEQUENCE {
+ -- Measurement objects
+ measObjectToRemoveList MeasObjectToRemoveList OPTIONAL, -- Need ON
+ measObjectToAddModList MeasObjectToAddModList OPTIONAL, -- Need ON
+ -- Reporting configurations
+ reportConfigToRemoveList ReportConfigToRemoveList OPTIONAL, -- Need ON
+ reportConfigToAddModList ReportConfigToAddModList OPTIONAL, -- Need ON
+ -- Measurement identities
+ measIdToRemoveList MeasIdToRemoveList OPTIONAL, -- Need ON
+ measIdToAddModList MeasIdToAddModList OPTIONAL, -- Need ON
+ -- Other parameters
+ quantityConfig QuantityConfig OPTIONAL, -- Need ON
+ measGapConfig MeasGapConfig OPTIONAL, -- Need ON
+ s-Measure RSRP-Range OPTIONAL, -- Need ON
+ preRegistrationInfoHRPD PreRegistrationInfoHRPD OPTIONAL, -- Need OP
+ speedStatePars CHOICE {
+ release NULL,
+ setup SEQUENCE {
+ mobilityStateParameters MobilityStateParameters,
+ timeToTrigger-SF SpeedStateScaleFactors
+ }
+ } OPTIONAL, -- Need ON
+ ...
+}
+
+MeasIdToRemoveList ::= SEQUENCE (SIZE (1..maxMeasId)) OF MeasId
+
+MeasObjectToRemoveList ::= SEQUENCE (SIZE (1..maxObjectId)) OF MeasObjectId
+
+ReportConfigToRemoveList ::= SEQUENCE (SIZE (1..maxReportConfigId)) OF ReportConfigId
+
+
+MeasGapConfig ::= CHOICE {
+ release NULL,
+ setup SEQUENCE {
+ gapOffset CHOICE {
+ gp0 INTEGER (0..39),
+ gp1 INTEGER (0..79),
+ ...
+ }
+ }
+}
+
+
+MeasId ::= INTEGER (1..maxMeasId)
+
+
+MeasIdToAddModList ::= SEQUENCE (SIZE (1..maxMeasId)) OF MeasIdToAddMod
+
+MeasIdToAddMod ::= SEQUENCE {
+ measId MeasId,
+ measObjectId MeasObjectId,
+ reportConfigId ReportConfigId
+}
+
+
+MeasObjectCDMA2000 ::= SEQUENCE {
+ cdma2000-Type CDMA2000-Type,
+ carrierFreq CarrierFreqCDMA2000,
+ searchWindowSize INTEGER (0..15) OPTIONAL, -- Need ON
+ offsetFreq Q-OffsetRangeInterRAT DEFAULT 0,
+ cellsToRemoveList CellIndexList OPTIONAL, -- Need ON
+ cellsToAddModList CellsToAddModListCDMA2000 OPTIONAL, -- Need ON
+ cellForWhichToReportCGI PhysCellIdCDMA2000 OPTIONAL, -- Need ON
+ ...
+}
+
+CellsToAddModListCDMA2000 ::= SEQUENCE (SIZE (1..maxCellMeas)) OF CellsToAddModCDMA2000
+
+CellsToAddModCDMA2000 ::= SEQUENCE {
+ cellIndex INTEGER (1..maxCellMeas),
+ physCellId PhysCellIdCDMA2000
+}
+
+
+MeasObjectEUTRA ::= SEQUENCE {
+ carrierFreq ARFCN-ValueEUTRA,
+ allowedMeasBandwidth AllowedMeasBandwidth,
+ presenceAntennaPort1 PresenceAntennaPort1,
+ neighCellConfig NeighCellConfig,
+ offsetFreq Q-OffsetRange DEFAULT dB0,
+ -- Neighbour cell list
+ cellsToRemoveList CellIndexList OPTIONAL, -- Need ON
+ cellsToAddModList CellsToAddModList OPTIONAL, -- Need ON
+ -- Black list
+ blackCellsToRemoveList CellIndexList OPTIONAL, -- Need ON
+ blackCellsToAddModList BlackCellsToAddModList OPTIONAL, -- Need ON
+ cellForWhichToReportCGI PhysCellId OPTIONAL, -- Need ON
+ ...
+}
+
+CellsToAddModList ::= SEQUENCE (SIZE (1..maxCellMeas)) OF CellsToAddMod
+
+CellsToAddMod ::= SEQUENCE {
+ cellIndex INTEGER (1..maxCellMeas),
+ physCellId PhysCellId,
+ cellIndividualOffset Q-OffsetRange
+}
+
+BlackCellsToAddModList ::= SEQUENCE (SIZE (1..maxCellMeas)) OF BlackCellsToAddMod
+
+BlackCellsToAddMod ::= SEQUENCE {
+ cellIndex INTEGER (1..maxCellMeas),
+ physCellIdRange PhysCellIdRange
+}
+
+
+MeasObjectGERAN ::= SEQUENCE {
+ carrierFreqs CarrierFreqsGERAN,
+ offsetFreq Q-OffsetRangeInterRAT DEFAULT 0,
+ ncc-Permitted BIT STRING(SIZE (8)) DEFAULT '11111111'B,
+ cellForWhichToReportCGI PhysCellIdGERAN OPTIONAL, -- Need ON
+ ...
+}
+
+
+MeasObjectId ::= INTEGER (1..maxObjectId)
+
+
+MeasObjectToAddModList ::= SEQUENCE (SIZE (1..maxObjectId)) OF MeasObjectToAddMod
+
+MeasObjectToAddMod ::= SEQUENCE {
+ measObjectId MeasObjectId,
+ measObject CHOICE {
+ measObjectEUTRA MeasObjectEUTRA,
+ measObjectUTRA MeasObjectUTRA,
+ measObjectGERAN MeasObjectGERAN,
+ measObjectCDMA2000 MeasObjectCDMA2000,
+ ...
+ }
+}
+
+
+MeasObjectUTRA ::= SEQUENCE {
+ carrierFreq ARFCN-ValueUTRA,
+ offsetFreq Q-OffsetRangeInterRAT DEFAULT 0,
+ cellsToRemoveList CellIndexList OPTIONAL, -- Need ON
+ cellsToAddModList CHOICE {
+ cellsToAddModListUTRA-FDD CellsToAddModListUTRA-FDD,
+ cellsToAddModListUTRA-TDD CellsToAddModListUTRA-TDD
+ } OPTIONAL, -- Need ON
+ cellForWhichToReportCGI CHOICE {
+ utra-FDD PhysCellIdUTRA-FDD,
+ utra-TDD PhysCellIdUTRA-TDD
+ } OPTIONAL, -- Need ON
+ ...
+}
+
+CellsToAddModListUTRA-FDD ::= SEQUENCE (SIZE (1..maxCellMeas)) OF CellsToAddModUTRA-FDD
+
+CellsToAddModUTRA-FDD ::= SEQUENCE {
+ cellIndex INTEGER (1..maxCellMeas),
+ physCellId PhysCellIdUTRA-FDD
+}
+
+CellsToAddModListUTRA-TDD ::= SEQUENCE (SIZE (1..maxCellMeas)) OF CellsToAddModUTRA-TDD
+
+CellsToAddModUTRA-TDD ::= SEQUENCE {
+ cellIndex INTEGER (1..maxCellMeas),
+ physCellId PhysCellIdUTRA-TDD
+}
+
+
+MeasResults ::= SEQUENCE {
+ measId MeasId,
+ measResultServCell SEQUENCE {
+ rsrpResult RSRP-Range,
+ rsrqResult RSRQ-Range
+ },
+ measResultNeighCells CHOICE {
+ measResultListEUTRA MeasResultListEUTRA,
+ measResultListUTRA MeasResultListUTRA,
+ measResultListGERAN MeasResultListGERAN,
+ measResultsCDMA2000 MeasResultsCDMA2000,
+ ...
+ } OPTIONAL,
+ ...,
+ [[ measResultForECID-r9 MeasResultForECID-r9 OPTIONAL
+ ]]
+}
+
+MeasResultListEUTRA ::= SEQUENCE (SIZE (1..maxCellReport)) OF MeasResultEUTRA
+
+MeasResultEUTRA ::= SEQUENCE {
+ physCellId PhysCellId,
+ cgi-Info SEQUENCE {
+ cellGlobalId CellGlobalIdEUTRA,
+ trackingAreaCode TrackingAreaCode,
+ plmn-IdentityList PLMN-IdentityList2 OPTIONAL
+ } OPTIONAL,
+ measResult SEQUENCE {
+ rsrpResult RSRP-Range OPTIONAL,
+ rsrqResult RSRQ-Range OPTIONAL,
+ ...,
+ [[ additionalSI-Info-r9 AdditionalSI-Info-r9 OPTIONAL
+ ]]
+ }
+}
+
+MeasResultListUTRA ::= SEQUENCE (SIZE (1..maxCellReport)) OF MeasResultUTRA
+
+MeasResultUTRA ::= SEQUENCE {
+ physCellId CHOICE {
+ fdd PhysCellIdUTRA-FDD,
+ tdd PhysCellIdUTRA-TDD
+ },
+ cgi-Info SEQUENCE {
+ cellGlobalId CellGlobalIdUTRA,
+ locationAreaCode BIT STRING (SIZE (16)) OPTIONAL,
+ routingAreaCode BIT STRING (SIZE (8)) OPTIONAL,
+ plmn-IdentityList PLMN-IdentityList2 OPTIONAL
+ } OPTIONAL,
+ measResult SEQUENCE {
+ utra-RSCP INTEGER (-5..91) OPTIONAL,
+ utra-EcN0 INTEGER (0..49) OPTIONAL,
+ ...,
+ [[ additionalSI-Info-r9 AdditionalSI-Info-r9 OPTIONAL
+ ]]
+ }
+}
+
+MeasResultListGERAN ::= SEQUENCE (SIZE (1..maxCellReport)) OF MeasResultGERAN
+
+MeasResultGERAN ::= SEQUENCE {
+ carrierFreq CarrierFreqGERAN,
+ physCellId PhysCellIdGERAN,
+ cgi-Info SEQUENCE {
+ cellGlobalId CellGlobalIdGERAN,
+ routingAreaCode BIT STRING (SIZE (8)) OPTIONAL
+ } OPTIONAL,
+ measResult SEQUENCE {
+ rssi INTEGER (0..63),
+ ...
+ }
+}
+
+MeasResultsCDMA2000 ::= SEQUENCE {
+ preRegistrationStatusHRPD BOOLEAN,
+ measResultListCDMA2000 MeasResultListCDMA2000
+}
+
+MeasResultListCDMA2000 ::= SEQUENCE (SIZE (1..maxCellReport)) OF MeasResultCDMA2000
+
+MeasResultCDMA2000 ::= SEQUENCE {
+ physCellId PhysCellIdCDMA2000,
+ cgi-Info CellGlobalIdCDMA2000 OPTIONAL,
+ measResult SEQUENCE {
+ pilotPnPhase INTEGER (0..32767) OPTIONAL,
+ pilotStrength INTEGER (0..63),
+ ...
+ }
+}
+
+MeasResultForECID-r9 ::= SEQUENCE {
+ ue-RxTxTimeDiffResult-r9 INTEGER (0..4095),
+ currentSFN-r9 BIT STRING (SIZE (10))
+}
+
+PLMN-IdentityList2 ::= SEQUENCE (SIZE (1..5)) OF PLMN-Identity
+
+AdditionalSI-Info-r9 ::= SEQUENCE {
+ csg-MemberStatus-r9 ENUMERATED {member} OPTIONAL,
+ csg-Identity-r9 CSG-Identity OPTIONAL
+}
+
+
+QuantityConfig ::= SEQUENCE {
+ quantityConfigEUTRA QuantityConfigEUTRA OPTIONAL, -- Need ON
+ quantityConfigUTRA QuantityConfigUTRA OPTIONAL, -- Need ON
+ quantityConfigGERAN QuantityConfigGERAN OPTIONAL, -- Need ON
+ quantityConfigCDMA2000 QuantityConfigCDMA2000 OPTIONAL, -- Need ON
+ ...
+}
+
+QuantityConfigEUTRA ::= SEQUENCE {
+ filterCoefficientRSRP FilterCoefficient DEFAULT fc4,
+ filterCoefficientRSRQ FilterCoefficient DEFAULT fc4
+}
+
+QuantityConfigUTRA ::= SEQUENCE {
+ measQuantityUTRA-FDD ENUMERATED {cpich-RSCP, cpich-EcN0},
+ measQuantityUTRA-TDD ENUMERATED {pccpch-RSCP},
+ filterCoefficient FilterCoefficient DEFAULT fc4
+}
+
+QuantityConfigGERAN ::= SEQUENCE {
+ measQuantityGERAN ENUMERATED {rssi},
+ filterCoefficient FilterCoefficient DEFAULT fc2
+}
+
+QuantityConfigCDMA2000 ::= SEQUENCE {
+ measQuantityCDMA2000 ENUMERATED {pilotStrength, pilotPnPhaseAndPilotStrength}
+}
+
+
+ReportConfigEUTRA ::= SEQUENCE {
+ triggerType CHOICE {
+ event SEQUENCE {
+ eventId CHOICE {
+ eventA1 SEQUENCE {
+ a1-Threshold ThresholdEUTRA
+ },
+ eventA2 SEQUENCE {
+ a2-Threshold ThresholdEUTRA
+ },
+ eventA3 SEQUENCE {
+ a3-Offset INTEGER (-30..30),
+ reportOnLeave BOOLEAN
+ },
+ eventA4 SEQUENCE {
+ a4-Threshold ThresholdEUTRA
+ },
+ eventA5 SEQUENCE {
+ a5-Threshold1 ThresholdEUTRA,
+ a5-Threshold2 ThresholdEUTRA
+ },
+ ...
+ },
+ hysteresis Hysteresis,
+ timeToTrigger TimeToTrigger
+ },
+ periodical SEQUENCE {
+ purpose ENUMERATED {
+ reportStrongestCells, reportCGI}
+ }
+ },
+ triggerQuantity ENUMERATED {rsrp, rsrq},
+ reportQuantity ENUMERATED {sameAsTriggerQuantity, both},
+ maxReportCells INTEGER (1..maxCellReport),
+ reportInterval ReportInterval,
+ reportAmount ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity},
+ ...,
+ [[ si-RequestForHO-r9 ENUMERATED {setup} OPTIONAL, -- Cond reportCGI
+ ue-RxTxTimeDiffPeriodical-r9 ENUMERATED {setup} OPTIONAL -- Need OR
+ ]]
+}
+
+ThresholdEUTRA ::= CHOICE{
+ threshold-RSRP RSRP-Range,
+ threshold-RSRQ RSRQ-Range
+}
+
+
+ReportConfigId ::= INTEGER (1..maxReportConfigId)
+
+
+ReportConfigInterRAT ::= SEQUENCE {
+ triggerType CHOICE {
+ event SEQUENCE {
+ eventId CHOICE {
+ eventB1 SEQUENCE {
+ b1-Threshold CHOICE {
+ b1-ThresholdUTRA ThresholdUTRA,
+ b1-ThresholdGERAN ThresholdGERAN,
+ b1-ThresholdCDMA2000 ThresholdCDMA2000
+ }
+ },
+ eventB2 SEQUENCE {
+ b2-Threshold1 ThresholdEUTRA,
+ b2-Threshold2 CHOICE {
+ b2-Threshold2UTRA ThresholdUTRA,
+ b2-Threshold2GERAN ThresholdGERAN,
+ b2-Threshold2CDMA2000 ThresholdCDMA2000
+ }
+ },
+ ...
+ },
+ hysteresis Hysteresis,
+ timeToTrigger TimeToTrigger
+ },
+ periodical SEQUENCE {
+ purpose ENUMERATED {
+ reportStrongestCells,
+ reportStrongestCellsForSON,
+ reportCGI}
+ }
+ },
+ maxReportCells INTEGER (1..maxCellReport),
+ reportInterval ReportInterval,
+ reportAmount ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity},
+ ...,
+ [[ si-RequestForHO-r9 ENUMERATED {setup} OPTIONAL -- Cond reportCGI
+ ]]
+}
+
+ThresholdUTRA ::= CHOICE{
+ utra-RSCP INTEGER (-5..91),
+ utra-EcN0 INTEGER (0..49)
+}
+
+ThresholdGERAN ::= INTEGER (0..63)
+
+ThresholdCDMA2000 ::= INTEGER (0..63)
+
+
+ReportConfigToAddModList ::= SEQUENCE (SIZE (1..maxReportConfigId)) OF ReportConfigToAddMod
+
+ReportConfigToAddMod ::= SEQUENCE {
+ reportConfigId ReportConfigId,
+ reportConfig CHOICE {
+ reportConfigEUTRA ReportConfigEUTRA,
+ reportConfigInterRAT ReportConfigInterRAT
+ }
+}
+
+
+
+ReportInterval ::= ENUMERATED {
+ ms120, ms240, ms480, ms640, ms1024, ms2048, ms5120, ms10240,
+ min1, min6, min12, min30, min60, spare3, spare2, spare1}
+
+
+RSRP-Range ::= INTEGER(0..97)
+
+
+RSRQ-Range ::= INTEGER(0..34)
+
+
+TimeToTrigger ::= ENUMERATED {
+ ms0, ms40, ms64, ms80, ms100, ms128, ms160, ms256,
+ ms320, ms480, ms512, ms640, ms1024, ms1280, ms2560,
+ ms5120}
+
+
+C-RNTI ::= BIT STRING (SIZE (16))
+
+
+DedicatedInfoCDMA2000 ::= OCTET STRING
+
+
+DedicatedInfoNAS ::= OCTET STRING
+
+
+FilterCoefficient ::= ENUMERATED {
+ fc0, fc1, fc2, fc3, fc4, fc5,
+ fc6, fc7, fc8, fc9, fc11, fc13,
+ fc15, fc17, fc19, spare1, ...}
+
+
+MMEC ::= BIT STRING (SIZE (8))
+
+
+NeighCellConfig ::= BIT STRING (SIZE (2))
+
+
+OtherConfig-r9 ::= SEQUENCE {
+ reportProximityConfig-r9 ReportProximityConfig-r9 OPTIONAL, -- Need ON
+ ...
+}
+
+ReportProximityConfig-r9 ::= SEQUENCE {
+ proximityIndicationEUTRA-r9 ENUMERATED {enabled} OPTIONAL, -- Need OR
+ proximityIndicationUTRA-r9 ENUMERATED {enabled} OPTIONAL -- Need OR
+}
+
+
+RAND-CDMA2000 ::= BIT STRING (SIZE (32))
+
+
+RAT-Type ::= ENUMERATED {
+ eutra, utra, geran-cs, geran-ps, cdma2000-1XRTT,
+ spare3, spare2, spare1, ...}
+
+
+RRC-TransactionIdentifier ::= INTEGER (0..3)
+
+
+S-TMSI ::= SEQUENCE {
+ mmec MMEC,
+ m-TMSI BIT STRING (SIZE (32))
+}
+
+
+UE-CapabilityRAT-ContainerList ::=SEQUENCE (SIZE (0..maxRAT-Capabilities)) OF UE-CapabilityRAT-Container
+
+UE-CapabilityRAT-Container ::= SEQUENCE {
+ rat-Type RAT-Type,
+ ueCapabilityRAT-Container OCTET STRING
+}
+
+
+UE-EUTRA-Capability ::= SEQUENCE {
+ accessStratumRelease AccessStratumRelease,
+ ue-Category INTEGER (1..5),
+ pdcp-Parameters PDCP-Parameters,
+ phyLayerParameters PhyLayerParameters,
+ rf-Parameters RF-Parameters,
+ measParameters MeasParameters,
+ featureGroupIndicators BIT STRING (SIZE (32)) OPTIONAL,
+ interRAT-Parameters SEQUENCE {
+ utraFDD IRAT-ParametersUTRA-FDD OPTIONAL,
+ utraTDD128 IRAT-ParametersUTRA-TDD128 OPTIONAL,
+ utraTDD384 IRAT-ParametersUTRA-TDD384 OPTIONAL,
+ utraTDD768 IRAT-ParametersUTRA-TDD768 OPTIONAL,
+ geran IRAT-ParametersGERAN OPTIONAL,
+ cdma2000-HRPD IRAT-ParametersCDMA2000-HRPD OPTIONAL,
+ cdma2000-1xRTT IRAT-ParametersCDMA2000-1XRTT OPTIONAL
+ },
+ nonCriticalExtension UE-EUTRA-Capability-v920-IEs OPTIONAL
+}
+
+UE-EUTRA-Capability-v920-IEs ::= SEQUENCE {
+ phyLayerParameters-v920 PhyLayerParameters-v920,
+ interRAT-ParametersGERAN-v920 IRAT-ParametersGERAN-v920,
+ interRAT-ParametersUTRA-v920 IRAT-ParametersUTRA-v920 OPTIONAL,
+ interRAT-Parameters-v920 IRAT-ParametersCDMA2000-1XRTT-v920 OPTIONAL,
+ deviceType-r9 ENUMERATED {noBenFromBatConsumpOpt} OPTIONAL,
+ csg-ProximityIndicationParameters-r9 CSG-ProximityIndicationParameters-r9,
+ neighCellSI-AcquisitionParameters-r9 NeighCellSI-AcquisitionParameters-r9,
+ son-Parameters-r9 SON-Parameters-r9,
+ nonCriticalExtension SEQUENCE {} OPTIONAL
+}
+
+AccessStratumRelease ::= ENUMERATED {
+ rel8, rel9, spare6, spare5, spare4, spare3,
+ spare2, spare1, ...}
+
+PDCP-Parameters ::= SEQUENCE {
+ supportedROHC-Profiles SEQUENCE {
+ profile0x0001 BOOLEAN,
+ profile0x0002 BOOLEAN,
+ profile0x0003 BOOLEAN,
+ profile0x0004 BOOLEAN,
+ profile0x0006 BOOLEAN,
+ profile0x0101 BOOLEAN,
+ profile0x0102 BOOLEAN,
+ profile0x0103 BOOLEAN,
+ profile0x0104 BOOLEAN
+ },
+ maxNumberROHC-ContextSessions ENUMERATED {
+ cs2, cs4, cs8, cs12, cs16, cs24, cs32,
+ cs48, cs64, cs128, cs256, cs512, cs1024,
+ cs16384, spare2, spare1} DEFAULT cs16,
+ ...
+}
+
+PhyLayerParameters ::= SEQUENCE {
+ ue-TxAntennaSelectionSupported BOOLEAN,
+ ue-SpecificRefSigsSupported BOOLEAN
+}
+
+PhyLayerParameters-v920 ::= SEQUENCE {
+ enhancedDualLayerFDD-Supported-r9 BOOLEAN,
+ enhancedDualLayerTDD-Supported-r9 BOOLEAN
+}
+
+RF-Parameters ::= SEQUENCE {
+ supportedBandListEUTRA SupportedBandListEUTRA
+}
+
+SupportedBandListEUTRA ::= SEQUENCE (SIZE (1..maxBands)) OF SupportedBandEUTRA
+
+SupportedBandEUTRA ::= SEQUENCE {
+ bandEUTRA INTEGER (1..64),
+ halfDuplex BOOLEAN
+}
+
+MeasParameters ::= SEQUENCE {
+ bandListEUTRA BandListEUTRA
+}
+
+BandListEUTRA ::= SEQUENCE (SIZE (1..maxBands)) OF BandInfoEUTRA
+
+BandInfoEUTRA ::= SEQUENCE {
+ interFreqBandList InterFreqBandList,
+ interRAT-BandList InterRAT-BandList OPTIONAL
+}
+
+InterFreqBandList ::= SEQUENCE (SIZE (1..maxBands)) OF InterFreqBandInfo
+
+InterFreqBandInfo ::= SEQUENCE {
+ interFreqNeedForGaps BOOLEAN
+}
+
+InterRAT-BandList ::= SEQUENCE (SIZE (1..maxBands)) OF InterRAT-BandInfo
+
+InterRAT-BandInfo ::= SEQUENCE {
+ interRAT-NeedForGaps BOOLEAN
+}
+
+IRAT-ParametersUTRA-FDD ::= SEQUENCE {
+ supportedBandListUTRA-FDD SupportedBandListUTRA-FDD
+}
+
+IRAT-ParametersUTRA-v920 ::= SEQUENCE {
+ e-Redirection-r9 ENUMERATED {supported}
+}
+
+SupportedBandListUTRA-FDD ::= SEQUENCE (SIZE (1..maxBands)) OF SupportedBandUTRA-FDD
+
+SupportedBandUTRA-FDD ::= ENUMERATED {
+ bandI, bandII, bandIII, bandIV, bandV, bandVI,
+ bandVII, bandVIII, bandIX, bandX, bandXI,
+ bandXII, bandXIII, bandXIV, bandXV, bandXVI, ...}
+
+IRAT-ParametersUTRA-TDD128 ::= SEQUENCE {
+ supportedBandListUTRA-TDD128 SupportedBandListUTRA-TDD128
+}
+
+SupportedBandListUTRA-TDD128 ::= SEQUENCE (SIZE (1..maxBands)) OF SupportedBandUTRA-TDD128
+
+SupportedBandUTRA-TDD128 ::= ENUMERATED {
+ a, b, c, d, e, f, g, h, i, j, k, l, m, n,
+ o, p, ...}
+
+IRAT-ParametersUTRA-TDD384 ::= SEQUENCE {
+ supportedBandListUTRA-TDD384 SupportedBandListUTRA-TDD384
+}
+
+SupportedBandListUTRA-TDD384 ::= SEQUENCE (SIZE (1..maxBands)) OF SupportedBandUTRA-TDD384
+
+SupportedBandUTRA-TDD384 ::= ENUMERATED {
+ a, b, c, d, e, f, g, h, i, j, k, l, m, n,
+ o, p, ...}
+
+IRAT-ParametersUTRA-TDD768 ::= SEQUENCE {
+ supportedBandListUTRA-TDD768 SupportedBandListUTRA-TDD768
+}
+
+SupportedBandListUTRA-TDD768 ::= SEQUENCE (SIZE (1..maxBands)) OF SupportedBandUTRA-TDD768
+
+SupportedBandUTRA-TDD768 ::= ENUMERATED {
+ a, b, c, d, e, f, g, h, i, j, k, l, m, n,
+ o, p, ...}
+
+IRAT-ParametersGERAN ::= SEQUENCE {
+ supportedBandListGERAN SupportedBandListGERAN,
+ interRAT-PS-HO-ToGERAN BOOLEAN
+}
+
+IRAT-ParametersGERAN-v920 ::= SEQUENCE {
+ dtm-r9 ENUMERATED {supported} OPTIONAL,
+ e-RedirectionGERAN-r9 ENUMERATED {supported} OPTIONAL
+}
+
+SupportedBandListGERAN ::= SEQUENCE (SIZE (1..maxBands)) OF SupportedBandGERAN
+
+SupportedBandGERAN ::= ENUMERATED {
+ gsm450, gsm480, gsm710, gsm750, gsm810, gsm850,
+ gsm900P, gsm900E, gsm900R, gsm1800, gsm1900,
+ spare5, spare4, spare3, spare2, spare1, ...}
+
+IRAT-ParametersCDMA2000-HRPD ::= SEQUENCE {
+ supportedBandListHRPD SupportedBandListHRPD,
+ tx-ConfigHRPD ENUMERATED {single, dual},
+ rx-ConfigHRPD ENUMERATED {single, dual}
+}
+
+SupportedBandListHRPD ::= SEQUENCE (SIZE (1..maxCDMA-BandClass)) OF BandclassCDMA2000
+
+IRAT-ParametersCDMA2000-1XRTT ::= SEQUENCE {
+ supportedBandList1XRTT SupportedBandList1XRTT,
+ tx-Config1XRTT ENUMERATED {single, dual},
+ rx-Config1XRTT ENUMERATED {single, dual}
+}
+
+IRAT-ParametersCDMA2000-1XRTT-v920 ::= SEQUENCE {
+ e-CSFB-r9 ENUMERATED {supported},
+ e-CSFB-ConcPS-Mob-r9 ENUMERATED {notSupported, supported}
+}
+
+SupportedBandList1XRTT ::= SEQUENCE (SIZE (1..maxCDMA-BandClass)) OF BandclassCDMA2000
+
+CSG-ProximityIndicationParameters-r9 ::= SEQUENCE {
+ intraFreqProximityIndicationSupported-r9 BOOLEAN,
+ interFreqProximityIndicationSupported-r9 BOOLEAN,
+ utran-ProximityIndicationSupported-r9 BOOLEAN
+}
+
+NeighCellSI-AcquisitionParameters-r9 ::= SEQUENCE {
+ intraFreqSI-AcquisitionForHO-Supported-r9 BOOLEAN,
+ interFreqSI-AcquisitionForHO-Supported-r9 BOOLEAN,
+ utran-SI-AcquisitionForHO-Supported-r9 BOOLEAN
+}
+
+SON-Parameters-r9 ::= SEQUENCE {
+ rach-ReportSupported-r9 BOOLEAN
+}
+
+
+UE-TimersAndConstants ::= SEQUENCE {
+ t300 ENUMERATED {
+ ms100, ms200, ms300, ms400, ms600, ms1000, ms1500,
+ ms2000},
+ t301 ENUMERATED {
+ ms100, ms200, ms300, ms400, ms600, ms1000, ms1500,
+ ms2000},
+ t310 ENUMERATED {
+ ms0, ms50, ms100, ms200, ms500, ms1000, ms2000},
+ n310 ENUMERATED {
+ n1, n2, n3, n4, n6, n8, n10, n20},
+ t311 ENUMERATED {
+ ms1000, ms3000, ms5000, ms10000, ms15000,
+ ms20000, ms30000},
+ n311 ENUMERATED {
+ n1, n2, n3, n4, n5, n6, n8, n10},
+ ...
+}
+
+
+MBMS-NotificationConfig-r9 ::= SEQUENCE {
+ notificationRepetitionCoeff-r9 ENUMERATED {n2, n4},
+ notificationOffset-r9 INTEGER (0..10),
+ notificationSF-Index-r9 INTEGER (1..6)
+}
+
+
+MBSFN-AreaInfoList-r9 ::= SEQUENCE (SIZE(1..maxMBSFN-Area)) OF MBSFN-AreaInfo-r9
+
+MBSFN-AreaInfo-r9 ::= SEQUENCE {
+ mbsfn-AreaId-r9 INTEGER (0..255),
+ non-MBSFNregionLength ENUMERATED {s1, s2},
+ notificationIndicator-r9 INTEGER (0..7),
+ mcch-Config-r9 SEQUENCE {
+ mcch-RepetitionPeriod-r9 ENUMERATED {rf32, rf64, rf128, rf256},
+ mcch-Offset-r9 INTEGER (0..10),
+ mcch-ModificationPeriod-r9 ENUMERATED {rf512, rf1024},
+ sf-AllocInfo-r9 BIT STRING (SIZE(6)),
+ signallingMCS-r9 ENUMERATED {n2, n7, n13, n19}
+ },
+ ...
+}
+
+
+MBSFN-SubframeConfig ::= SEQUENCE {
+ radioframeAllocationPeriod ENUMERATED {n1, n2, n4, n8, n16, n32},
+ radioframeAllocationOffset INTEGER (0..7),
+ subframeAllocation CHOICE {
+ oneFrame BIT STRING (SIZE(6)),
+ fourFrames BIT STRING (SIZE(24))
+ }
+}
+
+PMCH-InfoList-r9 ::= SEQUENCE (SIZE (0..maxPMCH-PerMBSFN)) OF PMCH-Info-r9
+
+PMCH-Info-r9 ::= SEQUENCE {
+ pmch-Config-r9 PMCH-Config-r9,
+ mbms-SessionInfoList-r9 MBMS-SessionInfoList-r9,
+ ...
+}
+
+MBMS-SessionInfoList-r9 ::= SEQUENCE (SIZE (0..maxSessionPerPMCH)) OF MBMS-SessionInfo-r9
+
+MBMS-SessionInfo-r9 ::= SEQUENCE {
+ tmgi-r9 TMGI-r9,
+ sessionId-r9 OCTET STRING (SIZE (1)) OPTIONAL, -- Need OR
+ logicalChannelIdentity-r9 INTEGER (0..maxSessionPerPMCH-1),
+ ...
+}
+
+PMCH-Config-r9 ::= SEQUENCE {
+ sf-AllocEnd-r9 INTEGER (0..1535),
+ dataMCS-r9 INTEGER (0..28),
+ mch-SchedulingPeriod-r9 ENUMERATED {
+ rf8, rf16, rf32, rf64, rf128, rf256, rf512, rf1024},
+ ...
+}
+
+TMGI-r9 ::= SEQUENCE {
+ plmn-Id-r9 CHOICE {
+ plmn-Index-r9 INTEGER (1..6),
+ explicitValue-r9 PLMN-Identity
+ },
+ serviceId-r9 OCTET STRING (SIZE (3))
+}
+
+
+maxBands INTEGER ::= 64 -- Maximum number of bands listed in EUTRA UE caps
+maxCDMA-BandClass INTEGER ::= 32 -- Maximum value of the CDMA band classes
+maxCellBlack INTEGER ::= 16 -- Maximum number of blacklisted cells
+ -- listed in SIB type 4 and 5
+maxCellInter INTEGER ::= 16 -- Maximum number of neighbouring inter-frequency
+ -- cells listed in SIB type 5
+maxCellIntra INTEGER ::= 16 -- Maximum number of neighbouring intra-frequency
+ -- cells listed in SIB type 4
+maxCellMeas INTEGER ::= 32 -- Maximum number of entries in each of the neighbour
+ -- cell lists in a measurement object
+maxCellReport INTEGER ::= 8 -- Maximum number of reported cells
+maxDRB INTEGER ::= 11 -- Maximum number of Data Radio Bearers
+maxEARFCN INTEGER ::= 65535 -- Maximum value of EUTRA carrier fequency
+maxFreq INTEGER ::= 8 -- Maximum number of EUTRA carrier frequencies
+maxCellInfo-GERAN-r9 INTEGER ::= 32 -- Maximum number of GERAN cells for which system in-
+ -- formation can be provided as redirection assistance
+maxGERAN-SI INTEGER ::= 10 -- Maximum number of GERAN SI blocks that can be
+ -- provided as part of NACC information
+maxGNFG INTEGER ::= 16 -- Maximum number of GERAN neighbour freq groups
+maxMBSFN-Allocations INTEGER ::= 8 -- Maximum number of MBSFN frame allocations with
+ -- different offset
+maxMBSFN-Area INTEGER ::= 8
+maxSessionPerPMCH INTEGER ::= 29
+maxSessionPerPMCH-1 INTEGER ::= 28
+maxPMCH-PerMBSFN INTEGER ::= 15
+maxMeasId INTEGER ::= 32
+maxObjectId INTEGER ::= 32
+maxPageRec INTEGER ::= 16 --
+maxPNOffset INTEGER ::= 511 -- Maximum number of CDMA2000 PNOffsets
+maxRAT-Capabilities INTEGER ::= 8 -- Maximum number of interworking RATs (incl EUTRA)
+maxReportConfigId INTEGER ::= 32
+maxSIB INTEGER ::= 32 -- Maximum number of SIBs
+maxSIB-1 INTEGER ::= 31
+maxSI-Message INTEGER ::= 32 -- Maximum number of SI messages
+maxUTRA-FDD-Carrier INTEGER ::= 16 -- Maximum number of UTRA FDD carrier frequencies
+maxUTRA-TDD-Carrier INTEGER ::= 16 -- Maximum number of UTRA TDD carrier frequencies
+maxUTRA-CellInfo-r9 INTEGER ::= 16 -- Maximum number of cells for which system information
+ -- can be provided as redirection assistance
+
+
+END
diff --git a/lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn b/lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn
new file mode 100644
index 0000000000..fc244c30a2
--- /dev/null
+++ b/lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn
@@ -0,0 +1,82 @@
+--
+-- %CopyrightBegin%
+--
+-- Copyright Ericsson AB 2001-2010. All Rights Reserved.
+--
+-- The contents of this file are subject to the Erlang Public License,
+-- Version 1.1, (the "License"); you may not use this file except in
+-- compliance with the License. You should have received a copy of the
+-- Erlang Public License along with this software. If not, it can be
+-- retrieved online at http://www.erlang.org/.
+--
+-- Software distributed under the License is distributed on an "AS IS"
+-- basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+-- the License for the specific language governing rights and limitations
+-- under the License.
+--
+-- %CopyrightEnd%
+
+Extension-Addition-Group DEFINITIONS AUTOMATIC TAGS ::=
+
+BEGIN
+
+-- fetched from ITU-T Rec. X691 (07/2002)
+
+Ax ::= SEQUENCE {
+ a INTEGER (250..253),
+ b BOOLEAN,
+ c CHOICE {
+ d INTEGER,
+ ...,
+
+ [[
+ e BOOLEAN,
+ f IA5String
+ ]],
+ ...
+ },
+ ...,
+ [[
+ g NumericString (SIZE(3)),
+ h BOOLEAN OPTIONAL
+ ]]
+,
+ ...,
+ i BMPString OPTIONAL,
+ j PrintableString OPTIONAL
+
+}
+
+-- valAx Ax ::= { a 253, b TRUE, c e: TRUE, g "123", h TRUE }
+
+Ax2 ::= SEQUENCE {
+ a INTEGER (250..253),
+ b BOOLEAN,
+ ...,
+ ug NumericString
+
+}
+
+-- The value { a 253, b TRUE, c e: TRUE, g "123", h TRUE }
+-- is encoded in PER as
+-- Hexadecimal view
+-- 9E000180 010291A4
+
+-- is encoded in Unaligned PER as
+-- 9E000600 040A4690
+
+Ax3 ::= SEQUENCE {
+ a INTEGER (250..253),
+ b BOOLEAN,
+ s SEQUENCE {
+ sa INTEGER,
+ sb BOOLEAN,
+ ...,
+ [[
+ sextaddgroup INTEGER OPTIONAL
+ ]]
+ }
+}
+
+-- { a 253, b TRUE, s {sa 17, sb TRUE, sextaddgroup 11}}
+END
diff --git a/lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl b/lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl
new file mode 100644
index 0000000000..5fcec23756
--- /dev/null
+++ b/lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl
@@ -0,0 +1,132 @@
+%%%-------------------------------------------------------------------
+%%% File : extensionAdditionGroup.erl
+%%% Author : Kenneth Lundin
+%%% Description :
+%%%
+%%% Created : 18 May 2010 by kenneth
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+
+%%%-------------------------------------------------------------------
+-module(extensionAdditionGroup).
+-include("Extension-Addition-Group.hrl").
+
+
+-compile(export_all).
+
+run(Erule) ->
+ Val = #'Ax'{a=253, b = true, c= {e,true}, g="123", h = true},
+ io:format("~p:~p~n",[Erule,Val]),
+ {ok,List}= asn1rt:encode('Extension-Addition-Group','Ax',Val),
+ Enc = iolist_to_binary(List),
+ io:format("~p~n",[Enc]),
+ {ok,Val2} = asn1rt:decode('Extension-Addition-Group','Ax',Enc),
+ io:format("~p~n",[Val2]),
+ case Val2 of
+ Val -> ok;
+ _ -> exit({expected,Val, got, Val2})
+ end.
+
+run2(Erule) ->
+ Val = #'Ax3'{a=253, b = true, s = #'Ax3_s'{sa = 11, sb = true, sextaddgroup = 17}},
+ io:format("~p:~p~n",[Erule,Val]),
+ {ok,List}= asn1rt:encode('Extension-Addition-Group','Ax3',Val),
+ Enc = iolist_to_binary(List),
+ io:format("~p~n",[Enc]),
+ {ok,Val2} = asn1rt:decode('Extension-Addition-Group','Ax3',Enc),
+ io:format("~p~n",[Val2]),
+ case Val2 of
+ Val -> ok;
+ _ -> exit({expected,Val, got, Val2})
+ end.
+
+run3(Erule) ->
+ Val =
+{'RRC-DL-DCCH-Message',
+ {c1,
+ {rrcConnectionReconfiguration,
+ {'RRC-RRCConnectionReconfiguration',0,
+ {c1,
+ {'rrcConnectionReconfiguration-r8',
+ {'RRC-RRCConnectionReconfiguration-r8-IEs',
+ {'RRC-MeasConfig',asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,
+ asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,
+ asn1_NOVALUE,asn1_NOVALUE},
+ asn1_NOVALUE,
+ [[80,66,0,5,10,0,5,0,24,11,7,84,54,33,0,1,1,0,0,0,1,39,5,66,127,0,0,1],
+ []],
+ {'RRC-RadioResourceConfigDedicated',
+ [{'RRC-SRB-ToAddMod',1,
+ {explicitValue,
+ {am,
+ {'RRC-RLC-Config_am',
+ {'RRC-UL-AM-RLC',ms45,pInfinity,kBinfinity,t4},
+ {'RRC-DL-AM-RLC',ms35,ms0}}}},
+ {explicitValue,
+ {'RRC-LogicalChannelConfig',
+ {'RRC-LogicalChannelConfig_ul-SpecificParameters',3,infinity,
+ ms50,0},
+ asn1_NOVALUE}}}],
+ [{'RRC-DRB-ToAddMod',3,3,
+ {'RRC-PDCP-Config',infinity,
+ {'RRC-PDCP-Config_rlc-AM',false},
+ asn1_NOVALUE,
+ {notUsed,'NULL'}},
+ {am,
+ {'RRC-RLC-Config_am',
+ {'RRC-UL-AM-RLC',ms70,p256,kBinfinity,t4},
+ {'RRC-DL-AM-RLC',ms35,ms40}}},
+ 3,
+ {'RRC-LogicalChannelConfig',
+ {'RRC-LogicalChannelConfig_ul-SpecificParameters',5,infinity,ms50,
+ 1},
+ asn1_NOVALUE}},
+ {'RRC-DRB-ToAddMod',4,4,
+ {'RRC-PDCP-Config',infinity,
+ {'RRC-PDCP-Config_rlc-AM',false},
+ asn1_NOVALUE,
+ {notUsed,'NULL'}},
+ {am,
+ {'RRC-RLC-Config_am',
+ {'RRC-UL-AM-RLC',ms70,p256,kBinfinity,t4},
+ {'RRC-DL-AM-RLC',ms35,ms40}}},
+ 4,
+ {'RRC-LogicalChannelConfig',
+ {'RRC-LogicalChannelConfig_ul-SpecificParameters',5,infinity,ms50,
+ 1},
+ asn1_NOVALUE}}],
+ asn1_NOVALUE,
+ {explicitValue,
+ {'RRC-MAC-MainConfig',
+ {'RRC-MAC-MainConfig_ul-SCH-Config',n4,sf10,sf10240,false},
+ asn1_NOVALUE,sf500,
+ {setup,{'RRC-MAC-MainConfig_phr-Config_setup',sf200,sf200,dB3}},
+ asn1_NOVALUE}},
+ asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE},
+ asn1_NOVALUE,asn1_NOVALUE}}}}}}},
+ io:format("~p:~p~n",[Erule,Val]),
+ {ok,List}= asn1rt:encode('EUTRA-RRC-Definitions','DL-DCCH-Message',Val),
+ Enc = iolist_to_binary(List),
+ io:format("Result from encode:~n~p~n",[Enc]),
+ {ok,Val2} = asn1rt:decode('EUTRA-RRC-Definitions','DL-DCCH-Message',Enc),
+ io:format("Result from decode:~n~p~n",[Val2]),
+ case Val2 of
+ Val -> ok;
+ _ -> exit({expected,Val, got, Val2})
+ end.
+
diff --git a/lib/asn1/test/asn1_appup_test.erl b/lib/asn1/test/asn1_appup_test.erl
index 81701328a6..4a60c814e8 100644
--- a/lib/asn1/test/asn1_appup_test.erl
+++ b/lib/asn1/test/asn1_appup_test.erl
@@ -21,7 +21,7 @@
%% Purpose: Verify the application specifics of the asn1 application
%%----------------------------------------------------------------------
-module(asn1_appup_test).
-
+-compile({no_auto_import,[error/1]}).
-compile(export_all).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/asn1/test/test_compile_options.erl b/lib/asn1/test/test_compile_options.erl
index 83f38c5e6d..5e027cdedb 100644
--- a/lib/asn1/test/test_compile_options.erl
+++ b/lib/asn1/test/test_compile_options.erl
@@ -132,7 +132,7 @@ verbose(Config) when is_list(Config) ->
?line ok = asn1ct:compile(Asn1File, [{i,DataDir},{outdir,OutDir},noobj,verbose]),
?line test_server:capture_stop(),
?line [Line0|_] = test_server:capture_get(),
- ?line lists:prefix("Erlang ASN.1 version", Line0),
+ ?line true = lists:prefix("Erlang ASN.1 version", Line0),
%% Test non-verbose compile
?line test_server:capture_start(),
diff --git a/lib/asn1/vsn.mk b/lib/asn1/vsn.mk
index b7e91e42a0..0399ff2732 100644
--- a/lib/asn1/vsn.mk
+++ b/lib/asn1/vsn.mk
@@ -1,323 +1,2 @@
#next version number to use is 1.6.15 | 1.7 | 2.0
-ASN1_VSN = 1.6.14
-
-TICKETS = OTP-8565 \
- OTP-8516
-
-TICKETS_1.6.14 = \
- OTP-8565 \
- OTP-8516
-
-TICKETS_1.6.13 = \
- OTP-8463
-
-TICKETS_1.6.12 = \
- OTP-8256
-
-TICKETS_1.6.11 = \
- OTP-8136 \
- OTP-8047 \
- OTP-8046 \
- OTP-8043 \
- OTP-7972
-
-TICKETS_1.6.10 = \
- OTP-7954 \
- OTP-7953
-
-TICKETS_1.6.10 = \
- OTP-7954 \
- OTP-7953
-
-TICKETS_1.6.9 = \
- OTP-7909 \
- OTP-7904
-
-TICKETS_1.6.8.1 = \
- OTP-7900 \
- OTP-7910
-
-TICKETS_1.6.8 = \
- OTP-7876
-
-TICKETS_1.6.7 = \
- OTP-7801 \
- OTP-7806
-
-TICKETS_1.6.6 = \
- OTP-7759 \
- OTP-7763
-
-TICKETS_1.6.5 = \
- OTP-7734
-
-TICKETS_1.6.4 = \
- OTP-7708
-
-TICKETS_1.6.3 = \
- OTP-7681 \
- OTP-7678
-
-TICKETS_1.6.2 = \
- OTP-7608
-
-TICKETS_1.6.1 = \
- OTP-7602 \
- OTP-7533 \
- OTP-7476 \
- OTP-7334 \
- OTP-7332 \
- OTP-7322 \
- OTP-7306 \
- OTP-7299 \
- OTP-7295 \
- OTP-7204 \
- OTP-7174 \
- OTP-7166
-
-TICKETS_1.6 = \
- OTP-7407 \
- OTP-7403 \
- OTP-7400 \
- OTP-7375 \
- OTP-7374 \
- OTP-7335
-
-TICKETS_1.5.2 = \
- OTP-7263 \
- OTP-7264 \
- OTP-7268 \
- OTP-7269 \
- OTP-7273
-
-TICKETS_1.5.1 = \
- OTP-7149 \
- OTP-7151 \
- OTP-7154 \
- OTP-7155 \
- OTP-7169 \
- OTP-7171 \
- OTP-7193 \
- OTP-7199
-
-TICKETS_1.5 = \
- OTP-6835 \
- OTP-6882
-
-TICKETS_1.4.7 = \
- OTP-6828
-
-TICKETS_1.4.6 = \
- OTP-5067 \
- OTP-6763 \
- OTP-6769 \
- OTP-6770 \
- OTP-6786
-
-TICKETS_1.4.5 = \
- OTP-6493 \
- OTP-6601 \
- OTP-6695 \
- OTP-6698 \
- OTP-6702 \
- OTP-6707 \
- OTP-6717
-
-TICKETS_1.4.4.14 = \
- OTP-6462 \
- OTP-6506
-
-TICKETS_1.4.4.13 = \
- OTP-6405
-
-TICKETS_1.4.4.12 = \
- OTP-6314
-
-TICKETS_1.4.4.11 = \
- OTP-6143
-
-TICKETS_1.4.4.10 = \
- OTP-6111 \
- OTP-5932
-
-TICKETS_1.4.4.9 = \
- OTP-5783 \
- OTP-5788 \
- OTP-5812 \
- OTP-5831 \
- OPT-5832
-
-TICKETS_1.4.4.8 = \
- OTP-5687 \
- OTP-5688 \
- OTP-5689 \
- OTP-5701 \
- OTP-5710
-
-TICKETS_1.4.4.7 = \
- OTP-5477 \
- OTP-5509 \
- OTP-5511 \
- OTP-5602 \
- OTP-5616
-
-TICKETS_1.4.4.6 = \
- OTP-5457 \
- OTP-5466
-
-TICKETS_1.4.4.5 = \
- OTP-5302 \
- OTP-5378
-
-TICKETS_1.4.4.4 = \
- OTP-5240 \
- OTP-5243
-
-TICKETS_1.4.4.3 = \
- OTP-5103 \
- OTP-5104
-
-TICKETS_1.4.4.2 = \
- OTP-5022
-
-TICKETS_1.4.4.1 = \
- OTP-4970
-
-TICKETS_1.4.4 = \
- OTP-4893 \
- OTP-4894 \
- OTP-4895 \
- OTP-4917 \
- OTP-4918 \
- OTP-4919 \
- OTP-4944 \
- OTP-4953 \
- OTP-4955 \
- OTP-4957 \
- OTP-4965
-
-TICKETS_1.4.3.1 = \
- OTP-4866 \
- OTP-4869 \
- OTP-4872
-
-TICKETS_1.4.3 = \
- OTP-4832 \
- OTP-4833 \
- OTP-4835 \
- OTP-4856
-
-TICKETS_1.4.2.1 = \
- OTP-4773 \
- OTP-4791 \
- OTP-4792 \
- OTP-4797 \
- OTP-4798 \
- OTP-4799 \
- OTP-4809
-
-# OTP R9C
-TICKETS_1.4.2 = \
- OTP-4693 \
- OTP-4744
-
-TICKETS_1.4.1.1 = \
- OTP-4663 \
- OTP-4665 \
- OTP-4666
-
-TICKETS_1.4.1 = \
- OTP-4559 \
- OTP-4560 \
- OTP-4590 \
- OTP-4591 \
- OTP-4592 \
- OTP-4631 \
- OTP-4633
-
-TICKETS_1.4 = \
- OTP-3304
-
-TICKETS_1.3.3.1 = \
- OTP-4353 \
- OTP-4354 \
- OTP-4390 \
- OTP-4395
-
-TICKETS_1.3.3 = \
- OTP-4381 \
- OTP-4358 \
- OTP-4355 \
- OTP-4275 \
- OTP-4248 \
- OTP-4247 \
- OTP-4242 \
- OTP-4235 \
- OTP-4234 \
- OTP-4232 \
- OTP-4200 \
- OTP-4161 \
- OTP-4129
-
-TICKETS_1.3.2 = \
- OTP-4094 \
- OTP-4103 \
- OTP-3980 \
- OTP-4073
-
-TICKETS_1.3.1.1 = \
- OTP-4037 \
- OTP-4057 \
- OTP-4058
-
-TICKETS_1.3.1 = \
- OTP-4025 \
- OTP-4026
-
-TICKETS_1.3 = \
- OTP-3463 \
- OTP-3659 \
- OTP-3978 \
- OTP-3979 \
- OTP-3981 \
- OTP-3982 \
- OTP-3983 \
- OTP-3985 \
- OTP-3988 \
- OTP-3984 \
- OTP-3994
-
-TICKETS_1.2.9.6 = \
- OTP-3830
-
-TICKETS_1.2.9.5 = \
- OTP-3713 \
- OTP-3796 \
- OTP-3811
-
-TICKETS_1.2.9.3 = \
- OTP-3700 \
- OTP-3701
-
-TICKETS_1.2.9.2 = \
- OTP-xxxx
-
-TICKETS_1.2.9.1 = \
- OTP-xxxx
-
-TICKETS_1.2.9 = \
- OTP-3569 \
- OTP-3573
-
-TICKETS_1.2.8 = \
- OTP-3496
-
-TICKETS_1.2.7 = \
- OTP-3395
-
-TICKETS_1.2.6 = \
- OTP-3352
-
-TICKETS_1.2.5 = \
- OTP-3341
-
+ASN1_VSN = 1.6.14.1
diff --git a/lib/common_test/AUTHORS b/lib/common_test/AUTHORS
index 152ec1868f..ff443e89e8 100644
--- a/lib/common_test/AUTHORS
+++ b/lib/common_test/AUTHORS
@@ -5,3 +5,4 @@ Siri Hansen
Kenneth Lundin
Ingela Anderton
Niclas Eklund
+Andrey Pampukha
diff --git a/lib/common_test/doc/src/config_file_chapter.xml b/lib/common_test/doc/src/config_file_chapter.xml
index 850bc74e19..77b0c0c0b7 100644
--- a/lib/common_test/doc/src/config_file_chapter.xml
+++ b/lib/common_test/doc/src/config_file_chapter.xml
@@ -21,7 +21,7 @@
</legalnotice>
- <title>Config Files</title>
+ <title>External Configuration Data</title>
<prepared>Siri Hansen, Peter Andersson</prepared>
<docno></docno>
<date></date>
@@ -32,16 +32,19 @@
<section>
<title>General</title>
- <p>The Common Test framework uses configuration files to
- describe data related to a test and/or an SUT (System Under Test).
- The configuration data makes it possible to change properties without
- changing the test program itself. Configuration data can for example be:</p>
+ <p>To avoid hard coding data values related to the test and/or SUT (System
+ Under Test) in the test suites, the data may instead be specified by means
+ of configuration files or strings that Common Test reads before
+ the start of a test run. External configuration data makes it possible to
+ change test properties without having to modify the actual test suites
+ using the data. Examples of configuration data:</p>
<list>
<item>Addresses to the test plant or other instruments</item>
- <item>Filenames for files needed by the test</item>
- <item>Program names for programs that shall be run by the test</item>
- <item>Any other variable that is needed by the test</item>
+ <item>User login information</item>
+ <item>Names of files needed by the test</item>
+ <item>Names of programs that should be executed during the test</item>
+ <item>Any other variable needed by the test</item>
</list>
</section>
@@ -51,12 +54,12 @@
<p>A configuration file can contain any number of elements of the type:</p>
<pre>
- {Key,Value}.</pre>
+ {CfgVarName,Value}.</pre>
<p>where</p>
<pre>
- Key = atom()
- Value = term() | [{Key,Value}]</pre>
+ CfgVarName = atom()
+ Value = term() | [{CfgVarName,Value}]</pre>
</section>
@@ -65,8 +68,8 @@
<marker id="require_config_data"></marker>
<p>In a test suite, one must <em>require</em> that a configuration
- variable exists before attempting to read the associated
- value in a test case.</p>
+ variable (<c>CfgVarName</c> in the definition above) exists before
+ attempting to read the associated value in a test case or config function.</p>
<p><c>require</c> is an assert statement that can be part of the <seealso
marker="write_test_chapter#suite">test suite info function</seealso> or
@@ -83,13 +86,13 @@
<p>A <c>require</c> statement in the test suite info- or test case
info-list should look like this:
- <c>{require,Required}</c> or <c>{require,Name,Required}</c>. The
- arguments <c>Name</c> and <c>Required</c> are the same as the
+ <c>{require,CfgVarName}</c> or <c>{require,AliasName,CfgVarName}</c>.
+ The arguments <c>AliasName</c> and <c>CfgVarName</c> are the same as the
arguments to <c>ct:require/[1,2]</c> which are described in the
reference manual for <seealso marker="ct">ct</seealso>.
- <c>Name</c> becomes an alias for the configuration variable
- <c>Required</c>, and can be used as reference to the configuration
- data value. The configuration variable may be associated with an
+ <c>AliasName</c> becomes an alias for the configuration variable,
+ and can be used as reference to the configuration data value.
+ The configuration variable may be associated with an
arbitrary number of alias names, but each name must be unique within
the same test suite. There are two main uses for alias names:</p>
<list>
diff --git a/lib/common_test/doc/src/notes.xml b/lib/common_test/doc/src/notes.xml
index eadfc83c07..af9dbfa9ec 100644
--- a/lib/common_test/doc/src/notes.xml
+++ b/lib/common_test/doc/src/notes.xml
@@ -32,6 +32,69 @@
<file>notes.xml</file>
</header>
+<section><title>Common_Test 1.5.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Returning {return_group_result,failed} from end_per_group
+ in a group that is part of a sequence, did not cause the
+ proceeding cases (or groups) to get skipped. This has
+ been fixed.</p>
+ <p>
+ Own Id: OTP-8753 Aux Id: seq11644 </p>
+ </item>
+ <item>
+ <p>
+ ct:install now works as the documentation describes.</p>
+ <p>
+ Own Id: OTP-8818 Aux Id: seq-11666 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Common Test has been updated to handle start options and
+ test specification terms for test case groups (and test
+ cases in groups). Also, an option named 'label', has been
+ added that associates the test run with a name that
+ Common Test prints in the overview HTML logs.</p>
+ <p>
+ Own Id: OTP-8725 Aux Id: OTP-8727 </p>
+ </item>
+ <item>
+ <p>
+ Andrey Pampukha has been added to the AUTHORS file. Thank
+ you Andrey for your work on configuration data handling,
+ Large Scale Testing improvements, and other useful
+ updates and fixes.</p>
+ <p>
+ Own Id: OTP-8803</p>
+ </item>
+ <item>
+ <p>
+ The Configuration Data chapter in the User's Guide has
+ been updated.</p>
+ <p>
+ Own Id: OTP-8804</p>
+ </item>
+ <item>
+ <p>
+ Milliseconds are now included in timestamps in Common
+ Test log entries. (Thanks to Tomas Johansson.)</p>
+ <p>
+ Own Id: OTP-8808</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Common_Test 1.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/common_test/priv/Makefile.in b/lib/common_test/priv/Makefile.in
index 6372bbc8d5..a6ac0f1a02 100644
--- a/lib/common_test/priv/Makefile.in
+++ b/lib/common_test/priv/Makefile.in
@@ -56,8 +56,8 @@ ifneq ($(findstring win32,$(TARGET)),win32)
#
# Files
#
-FILES =
-SCRIPTS =
+FILES = vts.tool
+SCRIPTS =
IMAGES = tile1.jpg
#
diff --git a/lib/common_test/src/ct.erl b/lib/common_test/src/ct.erl
index 8ae175f10d..1dbf83ee10 100644
--- a/lib/common_test/src/ct.erl
+++ b/lib/common_test/src/ct.erl
@@ -694,7 +694,7 @@ userdata(TestDir, Suite, Case) ->
%%%-----------------------------------------------------------------
-%%% @spec get_status() -> TestStatus | {error,Reason}
+%%% @spec get_status() -> TestStatus | {error,Reason} | no_tests_running
%%% TestStatus = [StatusElem]
%%% StatusElem = {current,{Suite,TestCase}} | {successful,Successful} |
%%% {failed,Failed} | {skipped,Skipped} | {total,Total}
diff --git a/lib/common_test/src/ct_config.erl b/lib/common_test/src/ct_config.erl
index dc6fcc66e5..6b75937668 100644
--- a/lib/common_test/src/ct_config.erl
+++ b/lib/common_test/src/ct_config.erl
@@ -48,7 +48,7 @@
-export([get_ref_from_name/1, get_name_from_ref/1, get_key_from_name/1]).
--export([check_config_files/1, prepare_config_list/1]).
+-export([check_config_files/1, add_default_callback/1, prepare_config_list/1]).
-export([add_config/2, remove_config/2]).
@@ -212,6 +212,24 @@ get_config_file_list(Opts) ->
process_user_configs(Opts, []),
CfgFiles.
+add_default_callback(Opts) ->
+ case lists:keytake(config, 1, Opts) of
+ {value, {config, [File | _] = Files}, NoConfigOpts}
+ when is_integer(File) =/= true ->
+ [{config, lists:flatmap(fun add_def_cb/1, Files)} | NoConfigOpts];
+ {value, {config, File}, NoConfigOpts} ->
+ [{config, add_def_cb(File)} | NoConfigOpts];
+ false ->
+ Opts
+ end.
+
+add_def_cb([]) ->
+ [];
+add_def_cb(Config) when is_tuple(Config) ->
+ [Config];
+add_def_cb([H|_T] = Config ) when is_integer(H) ->
+ [{?ct_config_txt, [Config]}].
+
read_config_files(Opts) ->
AddCallback = fun(CallBack, []) ->
[{CallBack, []}];
@@ -220,16 +238,16 @@ read_config_files(Opts) ->
(CallBack, [F|_]=Files) when is_list(F) ->
lists:map(fun(X) -> {CallBack, X} end, Files)
end,
+
ConfigFiles = case lists:keyfind(config, 1, Opts) of
- {config, ConfigLists}->
- lists:foldr(fun({Callback,Files}, Acc) ->
- AddCallback(Callback,Files) ++ Acc
- end,
- [],
- ConfigLists);
- false->
- []
- end,
+ {config,ConfigLists}->
+ lists:foldr(fun({Callback,Files}, Acc) ->
+ AddCallback(Callback,Files)
+ ++ Acc
+ end,[],ConfigLists);
+ false->
+ []
+ end,
read_config_files_int(ConfigFiles, fun store_config/3).
read_config_files_int([{Callback, File}|Files], FunToSave) ->
diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl
index f8ae7202e6..f8ace73cbf 100644
--- a/lib/common_test/src/ct_logs.erl
+++ b/lib/common_test/src/ct_logs.erl
@@ -384,11 +384,14 @@ maybe_log_timestamp() ->
[{"<i>~s</i>",[log_timestamp({MS,S,US})]}]})
end.
-log_timestamp(Now) ->
- put(log_timestamp,Now),
- {_,{H,M,S}} = calendar:now_to_local_time(Now),
- lists:flatten(io_lib:format("~2.2.0w:~2.2.0w:~2.2.0w",
- [H,M,S])).
+log_timestamp({MS,S,US}) ->
+ put(log_timestamp, {MS,S,US}),
+ {{Year,Month,Day}, {Hour,Min,Sec}} =
+ calendar:now_to_local_time({MS,S,US}),
+ MilliSec = trunc(US/1000),
+ lists:flatten(io_lib:format("~4.10.0B-~2.10.0B-~2.10.0B "
+ "~2.10.0B:~2.10.0B:~2.10.0B.~3.10.0B",
+ [Year,Month,Day,Hour,Min,Sec,MilliSec])).
%%%-----------------------------------------------------------------
%%% The logger server
@@ -461,9 +464,11 @@ logger_loop(State) ->
{'EXIT',_Reason} ->
Fd = State#logger_state.ct_log_fd,
io:format(Fd,
- "Logging fails! Str: ~p, Args: ~p~n",
+ "Logging fails! "
+ "Str: ~p, Args: ~p~n",
[Str,Args]),
- %% stop the testcase, we need to see the fault
+ %% stop the testcase, we need
+ %% to see the fault
exit(Pid,logging_failed),
ok;
IoStr when IoList == [] ->
diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl
index c5bfd01642..586b3893f1 100644
--- a/lib/common_test/src/ct_run.erl
+++ b/lib/common_test/src/ct_run.erl
@@ -550,6 +550,9 @@ install(Opts) ->
install(Opts, ".").
install(Opts, LogDir) ->
+
+ ConfOpts = ct_config:add_default_callback(Opts),
+
case application:get_env(common_test, decrypt) of
{ok,_} ->
ok;
@@ -566,7 +569,7 @@ install(Opts, LogDir) ->
VarFile = variables_file_name(LogDir),
case file:open(VarFile, [write]) of
{ok,Fd} ->
- [io:format(Fd, "~p.\n", [Opt]) || Opt <- Opts],
+ [io:format(Fd, "~p.\n", [Opt]) || Opt <- ConfOpts ],
file:close(Fd),
ok;
{error,Reason} ->
@@ -739,11 +742,12 @@ run_test1(StartOpts) ->
%% test specification
case proplists:get_value(spec, StartOpts) of
undefined ->
- case proplists:get_value(prepared_tests, StartOpts) of
- undefined -> % use dir|suite|case
- run_dir(Opts, StartOpts);
- {{Run,Skip},Specs} -> % use prepared tests
- run_prepared(Run, Skip, Opts#opts{testspecs = Specs}, StartOpts)
+ case lists:keysearch(prepared_tests, 1, StartOpts) of
+ {value,{_,{Run,Skip},Specs}} -> % use prepared tests
+ run_prepared(Run, Skip, Opts#opts{testspecs = Specs},
+ StartOpts);
+ false ->
+ run_dir(Opts, StartOpts)
end;
Specs ->
Relaxed = get_start_opt(allow_user_terms, value, false, StartOpts),
@@ -879,8 +883,10 @@ run_dir(Opts = #opts{logdir = LogDir,
case lists:keysearch(suite, 1, StartOpts) of
{value,{_,Suite}} when is_integer(hd(Suite)) ; is_atom(Suite) ->
{Dir,Mod} = S2M(Suite),
- case listify(proplists:get_value(group, StartOpts, [])) ++
- listify(proplists:get_value(testcase, StartOpts, [])) of
+ case groups_and_cases(proplists:get_value(group, StartOpts),
+ proplists:get_value(testcase, StartOpts)) of
+ Error = {error,_} ->
+ exit(Error);
[] ->
reformat_result(catch do_run(tests(Dir, listify(Mod)),
[], Opts1, StartOpts));
@@ -900,8 +906,10 @@ run_dir(Opts = #opts{logdir = LogDir,
Mod = if is_atom(Suite) -> Suite;
true -> list_to_atom(Suite)
end,
- case listify(proplists:get_value(group, StartOpts, [])) ++
- listify(proplists:get_value(testcase, StartOpts, [])) of
+ case groups_and_cases(proplists:get_value(group, StartOpts),
+ proplists:get_value(testcase, StartOpts)) of
+ Error = {error,_} ->
+ exit(Error);
[] ->
reformat_result(catch do_run(tests(Dir, listify(Mod)),
[], Opts1, StartOpts));
@@ -1087,11 +1095,13 @@ groups_and_cases(Gs, Cs) when ((Gs == undefined) or (Gs == [])) and
((Cs == undefined) or (Cs == [])) ->
[];
groups_and_cases(Gs, Cs) when Gs == undefined ; Gs == [] ->
- [list_to_atom(C) || C <- Cs];
+ [ensure_atom(C) || C <- listify(Cs)];
groups_and_cases(Gs, Cs) when Cs == undefined ; Cs == [] ->
- [{list_to_atom(G),all} || G <- Gs];
+ [{ensure_atom(G),all} || G <- listify(Gs)];
+groups_and_cases(G, Cs) when is_atom(G) ->
+ [{G,[ensure_atom(C) || C <- listify(Cs)]}];
groups_and_cases([G], Cs) ->
- [{list_to_atom(G),[list_to_atom(C) || C <- Cs]}];
+ [{ensure_atom(G),[ensure_atom(C) || C <- listify(Cs)]}];
groups_and_cases([_,_|_] , Cs) when Cs =/= [] ->
{error,multiple_groups_and_cases};
groups_and_cases(_Gs, _Cs) ->
@@ -1377,17 +1387,8 @@ suite_tuples([]) ->
[].
final_tests(Tests, Skip, Bad) ->
-
- %%! --- Thu Jun 24 15:47:27 2010 --- peppe was here!
- %%! io:format(user, "FINAL0 = ~p~nSKIP0 = ~p~n", [Tests, Skip]),
-
{Tests1,Skip1} = final_tests1(Tests, [], Skip, Bad),
Skip2 = final_skip(Skip1, []),
-
-
- %%! --- Thu Jun 24 15:47:27 2010 --- peppe was here!
- %%! io:format(user, "FINAL1 = ~p~nSKIP1 = ~p~n", [Tests1, Skip2]),
-
{Tests1,Skip2}.
final_tests1([{TestDir,Suites,_}|Tests], Final, Skip, Bad) when
diff --git a/lib/common_test/src/ct_slave.erl b/lib/common_test/src/ct_slave.erl
index d2a491e079..aa3413fa89 100644
--- a/lib/common_test/src/ct_slave.erl
+++ b/lib/common_test/src/ct_slave.erl
@@ -52,7 +52,7 @@
%%% NodeName = atom()
%%% @doc Starts an Erlang node with name <code>Node</code> on the local host.
%%% @see start/3
-start(Node)->
+start(Node) ->
start(gethostname(), Node).
%%%-----------------------------------------------------------------
@@ -70,7 +70,7 @@ start(Node)->
%%% @doc Starts an Erlang node with name <code>Node</code> on host
%%% <code>Host</code> with the default options.
%%% @see start/3
-start(Host, Node)->
+start(Host, Node) ->
start(Host, Node, []).
%%%-----------------------------------------------------------------
@@ -163,7 +163,7 @@ start(Host, Node)->
%%% <code>NodeName</code> is the name of current node in this case.</item>
%%% </list></p>
%%%
-start(Host, Node, Options)->
+start(Host, Node, Options) ->
ENode = enodename(Host, Node),
case erlang:is_alive() of
false->
@@ -189,7 +189,7 @@ start(Host, Node, Options)->
%%% NodeName = atom()
%%% @doc Stops the running Erlang node with name <code>Node</code> on
%%% the localhost.
-stop(Node)->
+stop(Node) ->
stop(gethostname(), Node).
%%% @spec stop(Host, Node) -> Result
@@ -202,7 +202,7 @@ stop(Node)->
%%% NodeName = atom()
%%% @doc Stops the running Erlang node with name <code>Node</code> on
%%% host <code>Host</code>.
-stop(Host, Node)->
+stop(Host, Node) ->
ENode = enodename(Host, Node),
case is_started(ENode) of
{true, connected}->
@@ -214,7 +214,7 @@ stop(Host, Node)->
end.
%%% fetch an option value from the tagged tuple list with default
-get_option_value(Key, OptionList, Default)->
+get_option_value(Key, OptionList, Default) ->
case lists:keyfind(Key, 1, OptionList) of
false->
Default;
@@ -223,7 +223,7 @@ get_option_value(Key, OptionList, Default)->
end.
%%% convert option list to the option record, fill all defaults
-fetch_options(Options)->
+fetch_options(Options) ->
UserName = get_option_value(username, Options, []),
Password = get_option_value(password, Options, []),
BootTimeout = get_option_value(boot_timeout, Options, 3),
@@ -240,23 +240,23 @@ fetch_options(Options)->
% send a message when slave node is started
% @hidden
-slave_started(ENode, MasterPid)->
+slave_started(ENode, MasterPid) ->
MasterPid ! {node_started, ENode},
ok.
% send a message when slave node has finished startup
% @hidden
-slave_ready(ENode, MasterPid)->
+slave_ready(ENode, MasterPid) ->
MasterPid ! {node_ready, ENode},
ok.
% start monitoring of the master node
% @hidden
-monitor_master(MasterNode)->
- spawn(fun()->monitor_master_int(MasterNode) end).
+monitor_master(MasterNode) ->
+ spawn(fun() -> monitor_master_int(MasterNode) end).
% code of the masterdeath-waiter process
-monitor_master_int(MasterNode)->
+monitor_master_int(MasterNode) ->
erlang:monitor_node(MasterNode, true),
receive
{nodedown, MasterNode}->
@@ -264,11 +264,11 @@ monitor_master_int(MasterNode)->
end.
% check if node is listed in the nodes()
-is_connected(ENode)->
+is_connected(ENode) ->
[N||N<-nodes(), N==ENode] == [ENode].
% check if node is alive (ping and disconnect if pingable)
-is_started(ENode)->
+is_started(ENode) ->
case is_connected(ENode) of
true->
{true, connected};
@@ -283,11 +283,11 @@ is_started(ENode)->
end.
% make a Erlang node name from name and hostname
-enodename(Host, Node)->
+enodename(Host, Node) ->
list_to_atom(atom_to_list(Node)++"@"++atom_to_list(Host)).
% performs actual start of the "slave" node
-do_start(Host, Node, Options)->
+do_start(Host, Node, Options) ->
ENode = enodename(Host, Node),
Functions =
lists:concat([[{ct_slave, slave_started, [ENode, self()]}],
@@ -338,7 +338,7 @@ do_start(Host, Node, Options)->
Result.
% are we using fully qualified hostnames
-long_or_short()->
+long_or_short() ->
case net_kernel:longnames() of
true->
" -name ";
@@ -347,7 +347,7 @@ long_or_short()->
end.
% get the localhost's name, depending on the using name policy
-gethostname()->
+gethostname() ->
Hostname = case net_kernel:longnames() of
true->
net_adm:localhost();
@@ -358,19 +358,19 @@ gethostname()->
list_to_atom(Hostname).
% get cmd for starting Erlang
-get_cmd(Node, Flags)->
+get_cmd(Node, Flags) ->
Cookie = erlang:get_cookie(),
"erl -detached -noinput -setcookie "++ atom_to_list(Cookie) ++
long_or_short() ++ atom_to_list(Node) ++ " " ++ Flags.
% spawn node locally
-spawn_local_node(Node, Options)->
+spawn_local_node(Node, Options) ->
ErlFlags = Options#options.erl_flags,
Cmd = get_cmd(Node, ErlFlags),
open_port({spawn, Cmd}, [stream]).
% start crypto and ssh if not yet started
-check_for_ssh_running()->
+check_for_ssh_running() ->
case application:get_application(crypto) of
undefined->
application:start(crypto),
@@ -385,7 +385,7 @@ check_for_ssh_running()->
end.
% spawn node remotely
-spawn_remote_node(Host, Node, Options)->
+spawn_remote_node(Host, Node, Options) ->
Username = Options#options.username,
Password = Options#options.password,
ErlFlags = Options#options.erl_flags,
@@ -403,16 +403,16 @@ spawn_remote_node(Host, Node, Options)->
ssh_connection:exec(SSHConnRef, SSHChannelId, get_cmd(Node, ErlFlags), infinity).
% call functions on a remote Erlang node
-call_functions(_Node, [])->
+call_functions(_Node, []) ->
ok;
-call_functions(Node, [{M, F, A}|Functions])->
+call_functions(Node, [{M, F, A}|Functions]) ->
rpc:call(Node, M, F, A),
call_functions(Node, Functions).
% wait N seconds until node is pingable
-wait_for_node_alive(_Node, 0)->
+wait_for_node_alive(_Node, 0) ->
pang;
-wait_for_node_alive(Node, N)->
+wait_for_node_alive(Node, N) ->
timer:sleep(1000),
case net_adm:ping(Node) of
pong->
@@ -422,14 +422,14 @@ wait_for_node_alive(Node, N)->
end.
% call init:stop on a remote node
-do_stop(ENode)->
+do_stop(ENode) ->
spawn(ENode, init, stop, []),
wait_for_node_dead(ENode, 5).
% wait N seconds until node is disconnected
-wait_for_node_dead(Node, 0)->
+wait_for_node_dead(Node, 0) ->
{error, stop_timeout, Node};
-wait_for_node_dead(Node, N)->
+wait_for_node_dead(Node, N) ->
timer:sleep(1000),
case lists:member(Node, nodes()) of
true->
diff --git a/lib/common_test/src/ct_util.erl b/lib/common_test/src/ct_util.erl
index 0a434666fa..b5ab4cbb6e 100644
--- a/lib/common_test/src/ct_util.erl
+++ b/lib/common_test/src/ct_util.erl
@@ -556,10 +556,37 @@ listenv(Telnet) ->
%%% @hidden
%%% @equiv ct:parse_table/1
parse_table(Data) ->
- [Heading|Lines]=
- [remove_space(string:tokens(L, "|"),[]) || L <- Data, hd(L)==$|],
+ {Heading, Rest} = get_headings(Data),
+ Lines = parse_row(Rest,[],size(Heading)),
{Heading,Lines}.
+get_headings(["|" ++ Headings | Rest]) ->
+ {remove_space(string:tokens(Headings, "|"),[]), Rest};
+get_headings([_ | Rest]) ->
+ get_headings(Rest);
+get_headings([]) ->
+ {{},[]}.
+
+parse_row(["|" ++ _ = Row | T], Rows, NumCols) when NumCols > 1 ->
+ case string:tokens(Row, "|") of
+ Values when length(Values) =:= NumCols ->
+ parse_row(T,[remove_space(Values,[])|Rows], NumCols);
+ Values when length(Values) < NumCols ->
+ parse_row([Row ++"\n"++ hd(T) | tl(T)], Rows, NumCols)
+ end;
+parse_row(["|" ++ _ = Row | T], Rows, 1 = NumCols) ->
+ case string:rchr(Row, $|) of
+ 1 ->
+ parse_row([Row ++"\n"++hd(T) | tl(T)], Rows, NumCols);
+ _Else ->
+ parse_row(T, [remove_space(string:tokens(Row,"|"),[])|Rows],
+ NumCols)
+ end;
+parse_row([_Skip | T], Rows, NumCols) ->
+ parse_row(T, Rows, NumCols);
+parse_row([], Rows, _NumCols) ->
+ lists:reverse(Rows).
+
remove_space([Str|Rest],Acc) ->
remove_space(Rest,[string:strip(string:strip(Str),both,$')|Acc]);
remove_space([],Acc) ->
diff --git a/lib/common_test/test/Makefile b/lib/common_test/test/Makefile
index 3fb0d627a0..f2fe3390cf 100644
--- a/lib/common_test/test/Makefile
+++ b/lib/common_test/test/Makefile
@@ -32,6 +32,8 @@ MODULES= \
ct_event_handler_SUITE \
ct_groups_test_1_SUITE \
ct_groups_test_2_SUITE \
+ ct_sequence_1_SUITE \
+ ct_repeat_1_SUITE \
ct_testspec_1_SUITE \
ct_skip_SUITE \
ct_error_SUITE \
@@ -92,7 +94,7 @@ release_spec: opt
release_tests_spec:
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) $(ERL_FILES) $(COVERFILE) $(RELSYSDIR)
- $(INSTALL_PROGRAM) common_test.spec $(RELSYSDIR)
+ $(INSTALL_DATA) common_test.spec $(RELSYSDIR)
chmod -f -R u+w $(RELSYSDIR)
@tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
diff --git a/lib/common_test/test/ct_config_SUITE.erl b/lib/common_test/test/ct_config_SUITE.erl
index 72ff781f82..fc15abc5bc 100644
--- a/lib/common_test/test/ct_config_SUITE.erl
+++ b/lib/common_test/test/ct_config_SUITE.erl
@@ -58,6 +58,9 @@ end_per_suite(Config) ->
init_per_testcase(TestCase, Config) ->
ct_test_support:init_per_testcase(TestCase, Config).
+end_per_testcase(install_config = TestCase, Config) ->
+ ok = rpc:call(proplists:get_value(ct_node, Config), ct_config, stop, []),
+ ct_test_support:end_per_testcase(TestCase, Config);
end_per_testcase(TestCase, Config) ->
ct_test_support:end_per_testcase(TestCase, Config).
@@ -66,12 +69,13 @@ all(doc) ->
all(suite) ->
[
- require,
- userconfig_static,
- userconfig_dynamic,
- testspec_legacy,
- testspec_static,
- testspec_dynamic
+ require,
+ install_config,
+ userconfig_static,
+ userconfig_dynamic,
+ testspec_legacy,
+ testspec_static,
+ testspec_dynamic
].
%%--------------------------------------------------------------------
@@ -84,6 +88,17 @@ require(Config) when is_list(Config) ->
{config, filename:join(DataDir, "config/config.txt")},
["config_static_SUITE"]).
+install_config(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ CTNode = proplists:get_value(ct_node, Config),
+ rpc:call(CTNode, ct, install,
+ [[{config, [filename:join(DataDir, "config/config.txt")]}]]),
+ case rpc:call(CTNode, ct_config, start, [interactive]) of
+ Pid when is_pid(Pid) ->
+ ok
+ end.
+
+
userconfig_static(Config) when is_list(Config) ->
DataDir = ?config(data_dir, Config),
run_test(config_static_SUITE,
@@ -135,6 +150,8 @@ testspec_dynamic(Config) when is_list(Config) ->
[]),
file:delete(filename:join(ConfigDir, "spec_dynamic.spec")).
+
+
%%%-----------------------------------------------------------------
%%% HELP FUNCTIONS
%%%-----------------------------------------------------------------
diff --git a/lib/common_test/test/ct_master_SUITE.erl b/lib/common_test/test/ct_master_SUITE.erl
index 87e2c3049a..e0e1f93db2 100644
--- a/lib/common_test/test/ct_master_SUITE.erl
+++ b/lib/common_test/test/ct_master_SUITE.erl
@@ -101,7 +101,7 @@ make_spec(DataDir, FileName, NodeNames, Suites, Config)->
NS = lists:map(fun(NodeName)->
{init, NodeName, [
- {node_start, [{startup_functions, []}, {monitor_master, false}]},
+ {node_start, [{startup_functions, []}, {monitor_master, true}]},
{eval, {erlang, nodes, []}}
]
}
diff --git a/lib/common_test/test/ct_misc_1_SUITE.erl b/lib/common_test/test/ct_misc_1_SUITE.erl
index eb6c6aa101..8c8b2d0d41 100644
--- a/lib/common_test/test/ct_misc_1_SUITE.erl
+++ b/lib/common_test/test/ct_misc_1_SUITE.erl
@@ -62,7 +62,7 @@ all(doc) ->
all(suite) ->
[
- beam_me_up
+ beam_me_up, parse_table
].
%%--------------------------------------------------------------------
@@ -106,6 +106,66 @@ beam_me_up(Config) when is_list(Config) ->
TestEvents = events_to_check(beam_me_up, 1),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+parse_table(suite) ->
+ [parse_table_empty, parse_table_single,
+ parse_table_multiline_row,
+ parse_table_one_column_multiline,
+ parse_table_one_column_simple].
+
+parse_table_empty(Config) when is_list(Config) ->
+
+ String = ["+----+-------+---------+---------+----------+------+--------+",
+ "| id | col11 | col2222 | col3333 | col4 | col5 | col6666 |",
+ "+----+-------+---------+---------+----------+------+--------+",
+ "+----+-------+---------+---------+----------+------+--------+",
+ "Query Done: 0 records selected"],
+
+ {{"id","col11","col2222","col3333","col4","col5","col6666"},[]} =
+ ct:parse_table(String).
+
+
+parse_table_single(Config) when is_list(Config) ->
+
+ String = ["+------+--------+--------------+------------+------------------+---------+--------+---------+-----------+",
+ "| id | col1 | col2 | col3 | col4 | col5 | col6 | col7 | col8 |",
+"+------+--------+--------------+------------+------------------+---------+--------+---------+-----------+",
+ "| 0 | 0 | -1407231560 | -256 | -1407231489 | 1500 | 1 | 1 | 1 |",
+ "+------+--------+--------------+------------+------------------+---------+--------+---------+-----------+"
+ "Query Done: 1 record selected"],
+
+ {{"id","col1","col2","col3","col4","col5","col6","col7","col8"},
+ [{"0","0","-1407231560","-256","-1407231489", "1500","1","1","1"}]} =
+ ct:parse_table(String).
+
+parse_table_multiline_row(Config) when is_list(Config) ->
+
+ String = ["+------+--------+--------------+------------+------------------+---------+--------+---------+-----------+",
+ "| id | col1 | col2 | col3 | col4 | col5 | col6 | col7 | col8 |",
+"+------+--------+--------------+------------+------------------+---------+--------+---------+-----------+",
+ "| 0 | 0 | Free test string",
+ " on more lines",
+ "than one",
+ "| -256 | -1407231489 | 1500 | 1 | 1 | 1 |",
+ "+------+--------+--------------+------------+------------------+---------+--------+---------+-----------+"
+ "Query Done: 1 record selected"],
+
+ {{"id","col1","col2","col3","col4","col5","col6","col7","col8"},
+ [{"0","0","Free test string\n on more lines\nthan one\n",
+ "-256","-1407231489", "1500","1","1","1"}]} =
+ ct:parse_table(String).
+
+parse_table_one_column_simple(Config) when is_list(Config) ->
+
+ String = ["|test|","|test value|"],
+
+ {{"test"},[{"test value"}]} = ct:parse_table(String).
+
+parse_table_one_column_multiline(Config) when is_list(Config) ->
+ String = ["|test|","|test","value|"],
+
+ {{"test"},[{"test\nvalue"}]} = ct:parse_table(String).
+
%%%-----------------------------------------------------------------
%%% HELP FUNCTIONS
%%%-----------------------------------------------------------------
diff --git a/lib/common_test/test/ct_repeat_1_SUITE.erl b/lib/common_test/test/ct_repeat_1_SUITE.erl
new file mode 100644
index 0000000000..1b4cafc9d3
--- /dev/null
+++ b/lib/common_test/test/ct_repeat_1_SUITE.erl
@@ -0,0 +1,1537 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%%-------------------------------------------------------------------
+%%% File: ct_repeat_1_SUITE.erl
+%%%
+%%% Description:
+%%% Test some simple test case group scenarios with repeat.
+%%%
+%%% The suites used for the test are located in the data directory.
+%%%-------------------------------------------------------------------
+-module(ct_repeat_1_SUITE).
+
+-compile(export_all).
+
+-include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+
+-define(eh, ct_test_support_eh).
+
+%%--------------------------------------------------------------------
+%% TEST SERVER CALLBACK FUNCTIONS
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% Description: Since Common Test starts another Test Server
+%% instance, the tests need to be performed on a separate node (or
+%% there will be clashes with logging processes etc).
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config1 = ct_test_support:init_per_suite(Config),
+ Config1.
+
+end_per_suite(Config) ->
+ ct_test_support:end_per_suite(Config).
+
+init_per_testcase(TestCase, Config) ->
+ ct_test_support:init_per_testcase(TestCase, Config).
+
+end_per_testcase(TestCase, Config) ->
+ ct_test_support:end_per_testcase(TestCase, Config).
+
+all(doc) ->
+ [];
+
+all(suite) ->
+ [repeat_cs,
+ repeat_cs_and_grs,
+ repeat_seq,
+ repeat_cs_until_any_ok,
+ repeat_gr_until_any_ok,
+ repeat_cs_until_any_fail,
+ repeat_gr_until_any_fail,
+ repeat_cs_until_all_ok,
+ repeat_gr_until_all_ok,
+ repeat_cs_until_all_fail,
+ repeat_gr_until_all_fail,
+ repeat_seq_until_any_fail,
+ repeat_shuffled_seq_until_any_fail
+ ].
+
+%%--------------------------------------------------------------------
+%% TEST CASES
+%%--------------------------------------------------------------------
+
+repeat_cs(Config) when is_list(Config) ->
+ execute(repeat_cs,
+ "repeat_1_SUITE", repeat_cs,
+ Config).
+%%%-------------------------------------------------------------------
+repeat_cs_and_grs(Config) when is_list(Config) ->
+ execute(repeat_cs_and_grs,
+ "repeat_1_SUITE", repeat_cs_and_grs,
+ Config).
+%%%-------------------------------------------------------------------
+repeat_seq(Config) when is_list(Config) ->
+ execute(repeat_seq,
+ "repeat_1_SUITE", repeat_seq,
+ Config).
+%%%-------------------------------------------------------------------
+repeat_cs_until_any_ok(Config) when is_list(Config) ->
+ execute(repeat_cs_until_any_ok,
+ "repeat_1_SUITE", repeat_cs_until_any_ok,
+ Config).
+%%%-------------------------------------------------------------------
+repeat_gr_until_any_ok(Config) when is_list(Config) ->
+ execute(repeat_gr_until_any_ok,
+ "repeat_1_SUITE", repeat_gr_until_any_ok,
+ Config).
+%%%-------------------------------------------------------------------
+repeat_cs_until_any_fail(Config) when is_list(Config) ->
+ execute(repeat_cs_until_any_fail,
+ "repeat_1_SUITE", repeat_cs_until_any_fail,
+ Config).
+%%%-------------------------------------------------------------------
+repeat_gr_until_any_fail(Config) when is_list(Config) ->
+ execute(repeat_gr_until_any_fail,
+ "repeat_1_SUITE", repeat_gr_until_any_fail,
+ Config).
+%%%-------------------------------------------------------------------
+repeat_cs_until_all_ok(Config) when is_list(Config) ->
+ execute(repeat_cs_until_all_ok,
+ "repeat_1_SUITE", repeat_cs_until_all_ok,
+ Config).
+%%%-------------------------------------------------------------------
+repeat_gr_until_all_ok(Config) when is_list(Config) ->
+ execute(repeat_gr_until_all_ok,
+ "repeat_1_SUITE", repeat_gr_until_all_ok,
+ Config).
+%%%-------------------------------------------------------------------
+repeat_cs_until_all_fail(Config) when is_list(Config) ->
+ execute(repeat_cs_until_all_fail,
+ "repeat_1_SUITE", repeat_cs_until_all_fail,
+ Config).
+%%%-------------------------------------------------------------------
+repeat_gr_until_all_fail(Config) when is_list(Config) ->
+ execute(repeat_gr_until_all_fail,
+ "repeat_1_SUITE", repeat_gr_until_all_fail,
+ Config).
+%%%-------------------------------------------------------------------
+repeat_seq_until_any_fail(Config) when is_list(Config) ->
+ execute(repeat_seq_until_any_fail,
+ "repeat_1_SUITE", repeat_seq_until_any_fail,
+ Config).
+%%%-------------------------------------------------------------------
+repeat_shuffled_seq_until_any_fail(Config) when is_list(Config) ->
+ execute(repeat_shuffled_seq_until_any_fail,
+ "repeat_1_SUITE", repeat_shuffled_seq_until_any_fail,
+ Config).
+
+%%%-----------------------------------------------------------------
+%%% HELP FUNCTIONS
+%%%-----------------------------------------------------------------
+execute(TestCase, SuiteName, Group, Config) ->
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join(DataDir, SuiteName),
+
+ {Opts,ERPid} = setup([{suite,Suite},{group,Group},{label,TestCase}], Config),
+ ok = ct_test_support:run(Opts, Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(TestCase,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config)),
+
+ TestEvents = events_to_check(TestCase),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+setup(Test, Config) ->
+ Opts0 = ct_test_support:get_opts(Config),
+ Level = ?config(trace_level, Config),
+ EvHArgs = [{cbm,ct_test_support},{trace_level,Level}],
+ Opts = Opts0 ++ [{event_handler,{?eh,EvHArgs}} | Test],
+ ERPid = ct_test_support:start_event_receiver(Config),
+ {Opts,ERPid}.
+
+reformat(Events, EH) ->
+ ct_test_support:reformat(Events, EH).
+%reformat(Events, _EH) ->
+% Events.
+
+%%%-----------------------------------------------------------------
+%%% TEST EVENTS
+%%%-----------------------------------------------------------------
+events_to_check(Test) ->
+ %% 2 tests (ct:run_test + script_start) is default
+ events_to_check(Test, 2).
+
+events_to_check(_, 0) ->
+ [];
+events_to_check(Test, N) ->
+ test_events(Test) ++ events_to_check(Test, N-1).
+
+test_events(repeat_cs) ->
+ [{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,unknown}},
+ [{?eh,tc_done,{repeat_1_SUITE,{init_per_group,repeat_cs,[]},ok}},
+ [{?eh,tc_done,{repeat_1_SUITE,{init_per_group,repeat_cs_1,[]},ok}},
+ {?eh,test_stats,{2,0,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,{end_per_group,repeat_cs_1,[]},ok}}],
+ [{?eh,tc_done,{repeat_1_SUITE,{init_per_group,repeat_cs_2,[{repeat,2}]},ok}},
+ {?eh,test_stats,{4,0,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,{end_per_group,repeat_cs_2,[{repeat,2}]},ok}}],
+ [{?eh,tc_done,{repeat_1_SUITE,{init_per_group,repeat_cs_2,[]},ok}},
+ {?eh,test_stats,{6,0,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,{end_per_group,repeat_cs_2,[]},ok}}],
+ {?eh,tc_done,{repeat_1_SUITE,{end_per_group,repeat_cs,[]},ok}}],
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
+test_events(repeat_cs_and_grs) ->
+ [{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,unknown}},
+ [{?eh,tc_done,{repeat_1_SUITE,{init_per_group,repeat_cs_and_grs,[{repeat,2}]},ok}},
+ [{?eh,tc_done,{repeat_1_SUITE,{init_per_group,gr_ok_1,[]},ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,{end_per_group,gr_ok_1,[]},ok}}],
+ {?eh,tc_done,{repeat_1_SUITE,tc_fail_1,{failed,{error,{{badmatch,2},'_'}}}}},
+ {?eh,test_stats,{1,1,{0,0}}},
+ [{?eh,tc_done,{repeat_1_SUITE,{init_per_group,gr_fail_result,[]},ok}},
+ {?eh,test_stats,{2,1,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,{end_per_group,gr_fail_result,[]},
+ {return_group_result,failed}}}],
+ {?eh,test_stats,{3,1,{0,0}}},
+ [{?eh,tc_done,{repeat_1_SUITE,{init_per_group,gr_fail_init,[]},
+ {failed,{error,fails_on_purpose}}}},
+ {?eh,tc_auto_skip,{repeat_1_SUITE,tc_ok_1,
+ {failed,{repeat_1_SUITE,init_per_group,
+ {'EXIT',fails_on_purpose}}}}},
+ {?eh,test_stats,{3,1,{0,1}}},
+ {?eh,tc_auto_skip,{repeat_1_SUITE,end_per_group,
+ {failed,{repeat_1_SUITE,init_per_group,
+ {'EXIT',fails_on_purpose}}}}}],
+ {?eh,test_stats,{4,1,{0,1}}},
+ {?eh,tc_done,{repeat_1_SUITE,{end_per_group,repeat_cs_and_grs,[{repeat,2}]},ok}}],
+ [{?eh,tc_done,{repeat_1_SUITE,{init_per_group,repeat_cs_and_grs,[]},ok}},
+ [{?eh,tc_done,{repeat_1_SUITE,{init_per_group,gr_ok_1,[]},ok}},
+ {?eh,test_stats,{5,1,{0,1}}},
+ {?eh,tc_done,{repeat_1_SUITE,{end_per_group,gr_ok_1,[]},ok}}],
+ {?eh,tc_done,{repeat_1_SUITE,tc_fail_1,{failed,{error,{{badmatch,2},'_'}}}}},
+ {?eh,test_stats,{5,2,{0,1}}},
+ [{?eh,tc_done,{repeat_1_SUITE,{init_per_group,gr_fail_result,[]},ok}},
+ {?eh,test_stats,{6,2,{0,1}}},
+ {?eh,tc_done,{repeat_1_SUITE,{end_per_group,gr_fail_result,[]},
+ {return_group_result,failed}}}],
+ {?eh,test_stats,{7,2,{0,1}}},
+ [{?eh,tc_done,{repeat_1_SUITE,{init_per_group,gr_fail_init,[]},
+ {failed,{error,fails_on_purpose}}}},
+ {?eh,tc_auto_skip,{repeat_1_SUITE,tc_ok_1,
+ {failed,{repeat_1_SUITE,init_per_group,
+ {'EXIT',fails_on_purpose}}}}},
+ {?eh,test_stats,{7,2,{0,2}}},
+ {?eh,tc_auto_skip,{repeat_1_SUITE,end_per_group,
+ {failed,{repeat_1_SUITE,init_per_group,
+ {'EXIT',fails_on_purpose}}}}}],
+ {?eh,test_stats,{8,2,{0,2}}},
+ {?eh,tc_done,{repeat_1_SUITE,{end_per_group,repeat_cs_and_grs,[]},ok}}],
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(repeat_seq) ->
+ [{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,start_info,{1,1,unknown}},
+ [{?eh,tc_done,{repeat_1_SUITE,{init_per_group,repeat_seq,[]},ok}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_seq_1,[sequence,{repeat,2}]},
+ ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+ {?eh,test_stats,{1,1,{0,0}}},
+ {?eh,tc_auto_skip,{repeat_1_SUITE,tc_ok_2,
+ {failed,{repeat_1_SUITE,tc_fail_1}}}},
+ {?eh,test_stats,{1,1,{0,1}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_seq_1,[sequence,{repeat,2}]},
+ ok}}],
+ [{?eh,tc_done,{repeat_1_SUITE,{init_per_group,repeat_seq_1,
+ [sequence]},ok}},
+ {?eh,test_stats,{2,2,{0,2}}},
+ {?eh,tc_done,{repeat_1_SUITE,{end_per_group,repeat_seq_1,
+ [sequence]},ok}}],
+
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_seq_2,[sequence,{repeat,2}]},
+ ok}},
+ {?eh,test_stats,{3,2,{0,2}}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,gr_fail_result,[]},ok}},
+ {?eh,test_stats,{4,2,{0,2}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,gr_fail_result,[]},
+ {return_group_result,failed}}}],
+ {?eh,tc_auto_skip,{repeat_1_SUITE,tc_ok_2,
+ {group_result,gr_fail_result,failed}}},
+ {?eh,test_stats,{4,2,{0,3}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_seq_2,[sequence,{repeat,2}]},
+ ok}}],
+ [{?eh,tc_done,
+ {repeat_1_SUITE,{init_per_group,repeat_seq_2,[sequence]},ok}},
+ {?eh,test_stats,{6,2,{0,4}}},
+ {?eh,tc_done,{repeat_1_SUITE,{end_per_group,repeat_seq_2,
+ [sequence]},ok}}],
+
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_seq_3,[sequence,{repeat,2}]},
+ ok}},
+ {?eh,test_stats,{7,2,{0,4}}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,gr_fail_init,[]},
+ {failed,{error,fails_on_purpose}}}},
+ {?eh,test_stats,{7,2,{0,5}}},
+ {?eh,tc_auto_skip,{repeat_1_SUITE,end_per_group,
+ {failed,
+ {repeat_1_SUITE,init_per_group,
+ {'EXIT',fails_on_purpose}}}}}],
+ {?eh,tc_auto_skip,{repeat_1_SUITE,tc_ok_2,
+ {group_result,gr_fail_init,failed}}},
+ {?eh,test_stats,{7,2,{0,6}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_seq_3,[sequence,{repeat,2}]},
+ ok}}],
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_seq_3,[sequence]},ok}},
+ {?eh,test_stats,{8,2,{0,8}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_seq_3,[sequence]},ok}}],
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_seq_4,[sequence,{repeat,2}]},
+ ok}},
+ {?eh,test_stats,{8,3,{0,8}}},
+ {?eh,tc_auto_skip,{repeat_1_SUITE,
+ tc_ok_1,{failed,{repeat_1_SUITE,tc_fail_1}}}},
+ {?eh,test_stats,{8,3,{0,9}}},
+ {?eh,tc_auto_skip,{repeat_1_SUITE,
+ tc_ok_1,{failed,{repeat_1_SUITE,tc_fail_1}}}},
+ {?eh,test_stats,{8,3,{0,10}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_seq_4,[sequence,{repeat,2}]},
+ ok}}],
+ [{?eh,tc_done,{repeat_1_SUITE,{init_per_group,repeat_seq_4,[sequence]},ok}},
+ {?eh,test_stats,{8,4,{0,12}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_seq_4,[sequence]},ok}}],
+
+ {?eh,tc_done,{repeat_1_SUITE,{end_per_group,repeat_seq,[]},ok}}],
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
+test_events(repeat_cs_until_any_ok) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,unknown}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_cs_until_any_ok,[]},ok}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_cs_until_any_ok_1,
+ [{repeat_until_any_ok,3}]},ok}},
+ {?eh,test_stats,{0,2,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_fail_then_ok_1,
+ {failed,{error,failing_this_time}}}},
+ {?eh,test_stats,{0,3,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_cs_until_any_ok_1,
+ [{repeat_until_any_ok,3}]},ok}}],
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_cs_until_any_ok_1,
+ [{repeat_until_any_ok,2}]},ok}},
+ {?eh,test_stats,{0,5,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_fail_then_ok_1,ok}},
+ {?eh,test_stats,{1,5,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_cs_until_any_ok_1,
+ [{repeat_until_any_ok,2}]},ok}}],
+
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_cs_until_any_ok_2,
+ [{repeat_until_any_ok,3}]},ok}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{2,5,{0,0}}},
+ {?eh,test_stats,{2,6,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_cs_until_any_ok_2,
+ [{repeat_until_any_ok,3}]},ok}}],
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_cs_until_any_ok,[]},ok}}],
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
+test_events(repeat_gr_until_any_ok) ->
+ [{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,unknown}},
+ [{?eh,tc_done,
+ {repeat_1_SUITE,{init_per_group,repeat_gr_until_any_ok,[]},ok}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_gr_until_any_ok_1,
+ [{repeat_until_any_ok,3}]},ok}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,gr_fail_result,[]},ok}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,gr_fail_result,[]},
+ {return_group_result,failed}}}],
+ {?eh,tc_done,{repeat_1_SUITE,tc_fail_1,
+ {failed,{error,{{badmatch,2},'_'}}}}},
+ {?eh,test_stats,{1,1,{0,0}}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,gr_fail_init,[]},
+ {failed,{error,fails_on_purpose}}}},
+ {?eh,test_stats,{1,1,{0,1}}},
+ {?eh,tc_auto_skip,{repeat_1_SUITE,end_per_group,
+ {failed,{repeat_1_SUITE,init_per_group,
+ {'EXIT',fails_on_purpose}}}}}],
+ {?eh,test_stats,{1,2,{0,1}}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,gr_fail_result_then_ok,[]},ok}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,gr_fail_result_then_ok,[]},
+ {return_group_result,failed}}}],
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_any_ok_1,
+ [{repeat_until_any_ok,3}]},ok}}],
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_gr_until_any_ok_1,
+ [{repeat_until_any_ok,2}]},ok}},
+ %% ...
+ {?eh,test_stats,{3,4,{0,2}}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,gr_fail_result_then_ok,[]},ok}},
+ {?eh,test_stats,{4,4,{0,2}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,gr_fail_result_then_ok,[]},ok}}],
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_any_ok_1,
+ [{repeat_until_any_ok,2}]},ok}}],
+
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_gr_until_any_ok_2,
+ [{repeat_until_any_ok,3}]},ok}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,gr_fail_result,[]},
+ {return_group_result,failed}}}],
+ {?eh,tc_done,{repeat_1_SUITE,tc_fail_1,
+ {failed,{error,{{badmatch,2},'_'}}}}},
+ {?eh,test_stats,{5,5,{0,2}}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_fail_then_ok_1,
+ {failed,{error,failing_this_time}}}},
+ {?eh,test_stats,{5,6,{0,2}}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,gr_fail_init,[]},
+ {failed,{error,fails_on_purpose}}}},
+ {?eh,test_stats,{5,6,{0,3}}},
+ {?eh,tc_auto_skip,{repeat_1_SUITE,end_per_group,
+ {failed,{repeat_1_SUITE,init_per_group,
+ {'EXIT',fails_on_purpose}}}}}],
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_any_ok_2,
+ [{repeat_until_any_ok,3}]},ok}}],
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_gr_until_any_ok_2,
+ [{repeat_until_any_ok,2}]},ok}},
+ {?eh,test_stats,{6,7,{0,3}}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_fail_then_ok_1}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_fail_then_ok_1,ok}},
+ {?eh,test_stats,{7,7,{0,3}}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,gr_fail_init,[]},
+ {failed,{error,fails_on_purpose}}}},
+ {?eh,test_stats,{7,7,{0,4}}},
+ {?eh,tc_auto_skip,{repeat_1_SUITE,end_per_group,
+ {failed,{repeat_1_SUITE,init_per_group,
+ {'EXIT',fails_on_purpose}}}}}],
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_any_ok_2,
+ [{repeat_until_any_ok,2}]},ok}}],
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_any_ok,[]},ok}}],
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
+test_events(repeat_cs_until_any_fail) ->
+ [{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,unknown}},
+ {?eh,tc_start,{repeat_1_SUITE,init_per_suite}},
+ {?eh,tc_done,{repeat_1_SUITE,init_per_suite,ok}},
+ [{?eh,tc_start,
+ {repeat_1_SUITE,{init_per_group,repeat_cs_until_any_fail,[]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,{init_per_group,repeat_cs_until_any_fail,[]},ok}},
+ [{?eh,tc_start,
+ {repeat_1_SUITE,
+ {init_per_group,repeat_cs_until_any_fail_1,
+ [{repeat_until_any_fail,3}]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,
+ {init_per_group,repeat_cs_until_any_fail_1,
+ [{repeat_until_any_fail,3}]},
+ ok}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_1}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_2}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_2,ok}},
+ {?eh,test_stats,{2,0,{0,0}}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_then_fail_1}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_then_fail_1,ok}},
+ {?eh,test_stats,{3,0,{0,0}}},
+ {?eh,tc_start,
+ {repeat_1_SUITE,
+ {end_per_group,repeat_cs_until_any_fail_1,
+ [{repeat_until_any_fail,3}]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,
+ {end_per_group,repeat_cs_until_any_fail_1,
+ [{repeat_until_any_fail,3}]},
+ ok}}],
+ [{?eh,tc_start,
+ {repeat_1_SUITE,
+ {init_per_group,repeat_cs_until_any_fail_1,
+ [{repeat_until_any_fail,2}]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,
+ {init_per_group,repeat_cs_until_any_fail_1,
+ [{repeat_until_any_fail,2}]},
+ ok}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_1}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{4,0,{0,0}}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_2}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_2,ok}},
+ {?eh,test_stats,{5,0,{0,0}}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_then_fail_1}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,tc_ok_then_fail_1,
+ {failed,{error,failing_this_time}}}},
+ {?eh,test_stats,{5,1,{0,0}}},
+ {?eh,tc_start,
+ {repeat_1_SUITE,
+ {end_per_group,repeat_cs_until_any_fail_1,
+ [{repeat_until_any_fail,2}]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,
+ {end_per_group,repeat_cs_until_any_fail_1,
+ [{repeat_until_any_fail,2}]},
+ ok}}],
+ [{?eh,tc_start,
+ {repeat_1_SUITE,
+ {init_per_group,repeat_cs_until_any_fail_2,
+ [{repeat_until_any_fail,3}]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,
+ {init_per_group,repeat_cs_until_any_fail_2,
+ [{repeat_until_any_fail,3}]},
+ ok}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_fail_1}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,tc_fail_1,
+ {failed,
+ {error,
+ {{badmatch,2},
+ [{repeat_1_SUITE,tc_fail_1,1},
+ {repeat_1_SUITE,tc_fail_1,1},
+ {test_server,my_apply,3},
+ {test_server,ts_tc,3},
+ {test_server,run_test_case_eval1,6},
+ {test_server,run_test_case_eval,8}]}}}}},
+ {?eh,test_stats,{5,2,{0,0}}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_fail_2}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,tc_fail_2,{failed,{error,exit_on_purpose}}}},
+ {?eh,test_stats,{5,3,{0,0}}},
+ {?eh,tc_start,
+ {repeat_1_SUITE,
+ {end_per_group,repeat_cs_until_any_fail_2,
+ [{repeat_until_any_fail,3}]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,
+ {end_per_group,repeat_cs_until_any_fail_2,
+ [{repeat_until_any_fail,3}]},
+ ok}}],
+ {?eh,tc_start,
+ {repeat_1_SUITE,{end_per_group,repeat_cs_until_any_fail,[]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,{end_per_group,repeat_cs_until_any_fail,[]},ok}}],
+ {?eh,tc_start,{repeat_1_SUITE,end_per_suite}},
+ {?eh,tc_done,{repeat_1_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
+test_events(repeat_gr_until_any_fail) ->
+ [{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,unknown}},
+ {?eh,tc_start,{repeat_1_SUITE,init_per_suite}},
+ {?eh,tc_done,{repeat_1_SUITE,init_per_suite,ok}},
+ [{?eh,tc_start,
+ {repeat_1_SUITE,{init_per_group,repeat_gr_until_any_fail,[]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,{init_per_group,repeat_gr_until_any_fail,[]},ok}},
+ [{?eh,tc_start,
+ {repeat_1_SUITE,
+ {init_per_group,repeat_gr_until_any_fail_1,
+ [{repeat_until_any_fail,3}]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,
+ {init_per_group,repeat_gr_until_any_fail_1,
+ [{repeat_until_any_fail,3}]},
+ ok}},
+ [{?eh,tc_start,
+ {repeat_1_SUITE,{init_per_group,gr_ok_1,[]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,{init_per_group,gr_ok_1,[]},ok}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_1}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+ {?eh,tc_start,
+ {repeat_1_SUITE,{end_per_group,gr_ok_1,[]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,{end_per_group,gr_ok_1,[]},ok}}],
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_1}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{2,0,{0,0}}},
+ [{?eh,tc_start,
+ {repeat_1_SUITE,{init_per_group,gr_ok_then_fail_result,[]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,{init_per_group,gr_ok_then_fail_result,[]},ok}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_1}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{3,0,{0,0}}},
+ {?eh,tc_start,
+ {repeat_1_SUITE,{end_per_group,gr_ok_then_fail_result,[]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,{end_per_group,gr_ok_then_fail_result,[]},ok}}],
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_2}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_2,ok}},
+ {?eh,test_stats,{4,0,{0,0}}},
+ {?eh,tc_start,
+ {repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_any_fail_1,
+ [{repeat_until_any_fail,3}]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_any_fail_1,
+ [{repeat_until_any_fail,3}]},
+ ok}}],
+ [{?eh,tc_start,
+ {repeat_1_SUITE,
+ {init_per_group,repeat_gr_until_any_fail_1,
+ [{repeat_until_any_fail,2}]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,
+ {init_per_group,repeat_gr_until_any_fail_1,
+ [{repeat_until_any_fail,2}]},
+ ok}},
+ [{?eh,tc_start,
+ {repeat_1_SUITE,{init_per_group,gr_ok_1,[]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,{init_per_group,gr_ok_1,[]},ok}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_1}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{5,0,{0,0}}},
+ {?eh,tc_start,
+ {repeat_1_SUITE,{end_per_group,gr_ok_1,[]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,{end_per_group,gr_ok_1,[]},ok}}],
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_1}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{6,0,{0,0}}},
+ [{?eh,tc_start,
+ {repeat_1_SUITE,{init_per_group,gr_ok_then_fail_result,[]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,{init_per_group,gr_ok_then_fail_result,[]},ok}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_1}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{7,0,{0,0}}},
+ {?eh,tc_start,
+ {repeat_1_SUITE,{end_per_group,gr_ok_then_fail_result,[]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,
+ {end_per_group,gr_ok_then_fail_result,[]},
+ {return_group_result,failed}}}],
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_2}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_2,ok}},
+ {?eh,test_stats,{8,0,{0,0}}},
+ {?eh,tc_start,
+ {repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_any_fail_1,
+ [{repeat_until_any_fail,2}]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_any_fail_1,
+ [{repeat_until_any_fail,2}]},
+ ok}}],
+ [{?eh,tc_start,
+ {repeat_1_SUITE,
+ {init_per_group,repeat_gr_until_any_fail_2,
+ [{repeat_until_any_fail,3}]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,
+ {init_per_group,repeat_gr_until_any_fail_2,
+ [{repeat_until_any_fail,3}]},
+ ok}},
+ [{?eh,tc_start,
+ {repeat_1_SUITE,{init_per_group,gr_ok_1,[]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,{init_per_group,gr_ok_1,[]},ok}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_1}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{9,0,{0,0}}},
+ {?eh,tc_start,
+ {repeat_1_SUITE,{end_per_group,gr_ok_1,[]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,{end_per_group,gr_ok_1,[]},ok}}],
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_1}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{10,0,{0,0}}},
+ [{?eh,tc_start,
+ {repeat_1_SUITE,{init_per_group,gr_ok_then_fail_init,[]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,{init_per_group,gr_ok_then_fail_init,[]},ok}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_1}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{11,0,{0,0}}},
+ {?eh,tc_start,
+ {repeat_1_SUITE,{end_per_group,gr_ok_then_fail_init,[]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,{end_per_group,gr_ok_then_fail_init,[]},ok}}],
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_2}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_2,ok}},
+ {?eh,test_stats,{12,0,{0,0}}},
+ {?eh,tc_start,
+ {repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_any_fail_2,
+ [{repeat_until_any_fail,3}]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_any_fail_2,
+ [{repeat_until_any_fail,3}]},
+ ok}}],
+ [{?eh,tc_start,
+ {repeat_1_SUITE,
+ {init_per_group,repeat_gr_until_any_fail_2,
+ [{repeat_until_any_fail,2}]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,
+ {init_per_group,repeat_gr_until_any_fail_2,
+ [{repeat_until_any_fail,2}]},
+ ok}},
+ [{?eh,tc_start,
+ {repeat_1_SUITE,{init_per_group,gr_ok_1,[]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,{init_per_group,gr_ok_1,[]},ok}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_1}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{13,0,{0,0}}},
+ {?eh,tc_start,
+ {repeat_1_SUITE,{end_per_group,gr_ok_1,[]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,{end_per_group,gr_ok_1,[]},ok}}],
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_1}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{14,0,{0,0}}},
+ [{?eh,tc_start,
+ {repeat_1_SUITE,{init_per_group,gr_ok_then_fail_init,[]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,
+ {init_per_group,gr_ok_then_fail_init,[]},
+ {failed,{error,failing_this_time}}}},
+ {?eh,tc_auto_skip,
+ {repeat_1_SUITE,tc_ok_1,
+ {failed,
+ {repeat_1_SUITE,init_per_group,
+ {'EXIT',failing_this_time}}}}},
+ {?eh,test_stats,{14,0,{0,1}}},
+ {?eh,tc_auto_skip,
+ {repeat_1_SUITE,end_per_group,
+ {failed,
+ {repeat_1_SUITE,init_per_group,
+ {'EXIT',failing_this_time}}}}}],
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_2}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_2,ok}},
+ {?eh,test_stats,{15,0,{0,1}}},
+ {?eh,tc_start,
+ {repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_any_fail_2,
+ [{repeat_until_any_fail,2}]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_any_fail_2,
+ [{repeat_until_any_fail,2}]},
+ ok}}],
+ [{?eh,tc_start,
+ {repeat_1_SUITE,
+ {init_per_group,repeat_gr_until_any_fail_3,
+ [{repeat_until_any_fail,3}]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,
+ {init_per_group,repeat_gr_until_any_fail_3,
+ [{repeat_until_any_fail,3}]},
+ ok}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_then_fail_1}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_then_fail_1,ok}},
+ {?eh,test_stats,{16,0,{0,1}}},
+ [{?eh,tc_start,
+ {repeat_1_SUITE,{init_per_group,gr_ok_1,[]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,{init_per_group,gr_ok_1,[]},ok}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_1}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{17,0,{0,1}}},
+ {?eh,tc_start,
+ {repeat_1_SUITE,{end_per_group,gr_ok_1,[]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,{end_per_group,gr_ok_1,[]},ok}}],
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_1}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{18,0,{0,1}}},
+ {?eh,tc_start,
+ {repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_any_fail_3,
+ [{repeat_until_any_fail,3}]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_any_fail_3,
+ [{repeat_until_any_fail,3}]},
+ ok}}],
+ [{?eh,tc_start,
+ {repeat_1_SUITE,
+ {init_per_group,repeat_gr_until_any_fail_3,
+ [{repeat_until_any_fail,2}]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,
+ {init_per_group,repeat_gr_until_any_fail_3,
+ [{repeat_until_any_fail,2}]},
+ ok}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_then_fail_1}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,tc_ok_then_fail_1,
+ {failed,{error,failing_this_time}}}},
+ {?eh,test_stats,{18,1,{0,1}}},
+ [{?eh,tc_start,
+ {repeat_1_SUITE,{init_per_group,gr_ok_1,[]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,{init_per_group,gr_ok_1,[]},ok}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_1}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{19,1,{0,1}}},
+ {?eh,tc_start,
+ {repeat_1_SUITE,{end_per_group,gr_ok_1,[]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,{end_per_group,gr_ok_1,[]},ok}}],
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_1}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{20,1,{0,1}}},
+ {?eh,tc_start,
+ {repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_any_fail_3,
+ [{repeat_until_any_fail,2}]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_any_fail_3,
+ [{repeat_until_any_fail,2}]},
+ ok}}],
+ {?eh,tc_start,
+ {repeat_1_SUITE,{end_per_group,repeat_gr_until_any_fail,[]}}},
+ {?eh,tc_done,
+ {repeat_1_SUITE,{end_per_group,repeat_gr_until_any_fail,[]},ok}}],
+ {?eh,tc_start,{repeat_1_SUITE,end_per_suite}},
+ {?eh,tc_done,{repeat_1_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
+test_events(repeat_cs_until_all_ok) ->
+ [{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,unknown}},
+ [{?eh,tc_done,{repeat_1_SUITE,{init_per_group,repeat_cs_until_all_ok,[]},ok}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_cs_until_all_ok_1,
+ [{repeat_until_all_ok,3}]},ok}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_fail_then_ok_1,
+ {failed,{error,failing_this_time}}}},
+ {?eh,test_stats,{0,1,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{1,1,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_fail_then_ok_2,
+ {failed,{error,failing_this_time}}}},
+ {?eh,test_stats,{1,2,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_cs_until_all_ok_1,
+ [{repeat_until_all_ok,3}]},ok}}],
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_cs_until_all_ok_1,
+ [{repeat_until_all_ok,2}]},ok}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_fail_then_ok_1,ok}},
+ {?eh,test_stats,{2,2,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{3,2,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_fail_then_ok_2,ok}},
+ {?eh,test_stats,{4,2,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_cs_until_all_ok_1,
+ [{repeat_until_all_ok,2}]},ok}}],
+
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_cs_until_all_ok_2,
+ [{repeat_until_all_ok,3}]},ok}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_2,ok}},
+ {?eh,test_stats,{6,2,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_cs_until_all_ok_2,
+ [{repeat_until_all_ok,3}]},ok}}],
+
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_cs_until_all_ok,[]},ok}}],
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
+test_events(repeat_gr_until_all_ok) ->
+ [{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,unknown}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_gr_until_all_ok,[]},ok}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_gr_until_all_ok_1,
+ [{repeat_until_all_ok,3}]},ok}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+ [{?eh,tc_done,{repeat_1_SUITE,{init_per_group,gr_ok_1,[]},ok}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{2,0,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,{end_per_group,gr_ok_1,[]},ok}}],
+ {?eh,tc_done,{repeat_1_SUITE,tc_fail_then_ok_1,
+ {failed,{error,failing_this_time}}}},
+ {?eh,test_stats,{2,1,{0,0}}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,gr_fail_result_then_ok,[]},ok}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{3,1,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,gr_fail_result_then_ok,[]},
+ {return_group_result,failed}}}],
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_all_ok_1,
+ [{repeat_until_all_ok,3}]},ok}}],
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_gr_until_all_ok_1,
+ [{repeat_until_all_ok,2}]},ok}},
+ {?eh,test_stats,{5,1,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_fail_then_ok_1,ok}},
+ {?eh,test_stats,{6,1,{0,0}}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,gr_fail_result_then_ok,[]},ok}},
+ {?eh,test_stats,{7,1,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,gr_fail_result_then_ok,[]},ok}}],
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_all_ok_1,
+ [{repeat_until_all_ok,2}]},ok}}],
+
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_gr_until_all_ok_2,
+ [{repeat_until_all_ok,3}]},ok}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,gr_fail_init_then_ok,[]},
+ {failed,{error,failing_this_time}}}},
+ {?eh,tc_auto_skip,{repeat_1_SUITE,tc_ok_1,
+ {failed,{repeat_1_SUITE,init_per_group,
+ {'EXIT',failing_this_time}}}}},
+ {?eh,test_stats,{7,1,{0,1}}},
+ {?eh,tc_auto_skip,{repeat_1_SUITE,end_per_group,
+ {failed,{repeat_1_SUITE,init_per_group,
+ {'EXIT',failing_this_time}}}}}],
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{8,1,{0,1}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_all_ok_2,
+ [{repeat_until_all_ok,3}]},ok}}],
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_gr_until_all_ok_2,
+ [{repeat_until_all_ok,2}]},ok}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,gr_fail_init_then_ok,[]},ok}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{9,1,{0,1}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,gr_fail_init_then_ok,[]},ok}}],
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{10,1,{0,1}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_all_ok_2,
+ [{repeat_until_all_ok,2}]},ok}}],
+
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_gr_until_all_ok_3,
+ [{repeat_until_all_ok,3}]},ok}},
+ [{?eh,tc_done,{repeat_1_SUITE,{init_per_group,gr_ok_1,[]},ok}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{11,1,{0,1}}},
+ {?eh,tc_done,{repeat_1_SUITE,{end_per_group,gr_ok_1,[]},ok}}],
+ {?eh,tc_done,{repeat_1_SUITE,tc_fail_then_ok_1,
+ {failed,{error,failing_this_time}}}},
+ {?eh,test_stats,{11,2,{0,1}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_all_ok_3,
+ [{repeat_until_all_ok,3}]},ok}}],
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_gr_until_all_ok_3,
+ [{repeat_until_all_ok,2}]},ok}},
+ [{?eh,tc_done,{repeat_1_SUITE,{init_per_group,gr_ok_1,[]},ok}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{12,2,{0,1}}},
+ {?eh,tc_done,{repeat_1_SUITE,{end_per_group,gr_ok_1,[]},ok}}],
+ {?eh,tc_done,{repeat_1_SUITE,tc_fail_then_ok_1,ok}},
+ {?eh,test_stats,{13,2,{0,1}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_all_ok_3,
+ [{repeat_until_all_ok,2}]},ok}}],
+
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_all_ok,[]},ok}}],
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
+test_events(repeat_cs_until_all_fail) ->
+ [{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,unknown}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_cs_until_all_fail,[]},ok}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_cs_until_all_fail_1,
+ [{repeat_until_all_fail,3}]},ok}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_then_fail_1,ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_fail_1}},
+ {?eh,test_stats,{1,1,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_then_fail_2,ok}},
+ {?eh,test_stats,{2,1,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_cs_until_all_fail_1,
+ [{repeat_until_all_fail,3}]},ok}}],
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_cs_until_all_fail_1,
+ [{repeat_until_all_fail,2}]},ok}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_then_fail_1,
+ {failed,{error,failing_this_time}}}},
+ {?eh,test_stats,{2,2,{0,0}}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_fail_1}},
+ {?eh,test_stats,{2,3,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_then_fail_2,
+ {failed,{error,failing_this_time}}}},
+ {?eh,test_stats,{2,4,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_cs_until_all_fail_1,
+ [{repeat_until_all_fail,2}]},ok}}],
+
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_cs_until_all_fail_2,
+ [{repeat_until_all_fail,3}]},ok}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_fail_1}},
+ {?eh,test_stats,{2,5,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_cs_until_all_fail_2,
+ [{repeat_until_all_fail,3}]},ok}}],
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_cs_until_all_fail,[]},ok}}],
+
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
+test_events(repeat_gr_until_all_fail) ->
+ [{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,unknown}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_gr_until_all_fail,[]},ok}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_gr_until_all_fail_1,
+ [{repeat_until_all_fail,3}]},ok}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_fail_1}},
+ {?eh,test_stats,{0,1,{0,0}}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,gr_fail_init,[]},
+ {failed,{error,fails_on_purpose}}}},
+ {?eh,test_stats,{0,1,{0,1}}},
+ {?eh,tc_auto_skip,{repeat_1_SUITE,end_per_group,
+ {failed,{repeat_1_SUITE,init_per_group,
+ {'EXIT',fails_on_purpose}}}}}],
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_then_fail_1,ok}},
+ {?eh,test_stats,{1,1,{0,1}}},
+ [{?eh,tc_done,{repeat_1_SUITE,{end_per_group,
+ gr_ok_then_fail_result,[]},ok}}],
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_all_fail_1,
+ [{repeat_until_all_fail,3}]},ok}}],
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_gr_until_all_fail_1,
+ [{repeat_until_all_fail,2}]},ok}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_fail_1}},
+ {?eh,test_stats,{2,2,{0,1}}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,gr_fail_init,[]},
+ {failed,{error,fails_on_purpose}}}},
+ {?eh,test_stats,{2,2,{0,2}}},
+ {?eh,tc_auto_skip,{repeat_1_SUITE,end_per_group,
+ {failed,{repeat_1_SUITE,init_per_group,
+ {'EXIT',fails_on_purpose}}}}}],
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_then_fail_1,
+ {failed,{error,failing_this_time}}}},
+ {?eh,test_stats,{2,3,{0,2}}},
+ [{?eh,tc_done,{repeat_1_SUITE,{init_per_group,
+ gr_ok_then_fail_result,[]},ok}},
+ {?eh,test_stats,{3,3,{0,2}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,gr_ok_then_fail_result,[]},
+ {return_group_result,failed}}}],
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_all_fail_1,
+ [{repeat_until_all_fail,2}]},ok}}],
+
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_gr_until_all_fail_2,
+ [{repeat_until_all_fail,3}]},ok}},
+ [{?eh,tc_done,{repeat_1_SUITE,{end_per_group,gr_ok_then_fail_init,[]},ok}}],
+ {?eh,tc_start,{repeat_1_SUITE,tc_fail_1}},
+ {?eh,test_stats,{4,4,{0,2}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_all_fail_2,
+ [{repeat_until_all_fail,3}]},ok}}],
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_gr_until_all_fail_2,
+ [{repeat_until_all_fail,2}]},ok}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,gr_ok_then_fail_init,[]},
+ {failed,{error,failing_this_time}}}},
+ {?eh,test_stats,{4,4,{0,3}}},
+ {?eh,tc_auto_skip,{repeat_1_SUITE,end_per_group,
+ {failed,{repeat_1_SUITE,init_per_group,
+ {'EXIT',failing_this_time}}}}}],
+ {?eh,tc_start,{repeat_1_SUITE,tc_fail_1}},
+ {?eh,test_stats,{4,5,{0,3}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_all_fail_2,
+ [{repeat_until_all_fail,2}]},ok}}],
+
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_gr_until_all_fail_3,
+ [{repeat_until_all_fail,3}]},ok}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,gr_fail_result,[]},
+ {return_group_result,failed}}}],
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_then_fail_1,ok}},
+ {?eh,test_stats,{6,5,{0,3}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_all_fail_3,
+ [{repeat_until_all_fail,3}]},ok}}],
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_gr_until_all_fail_3,
+ [{repeat_until_all_fail,2}]},ok}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,gr_fail_result,[]},
+ {return_group_result,failed}}}],
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_then_fail_1,
+ {failed,{error,failing_this_time}}}},
+ {?eh,test_stats,{7,6,{0,3}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_all_fail_3,
+ [{repeat_until_all_fail,2}]},ok}}],
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_gr_until_all_fail,[]},ok}}],
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
+test_events(repeat_seq_until_any_fail) ->
+ [{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,unknown}},
+
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_seq_until_any_fail,[]},ok}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_seq_until_any_fail_1,
+ [sequence,{repeat_until_any_fail,2}]},ok}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_2,ok}},
+ {?eh,test_stats,{2,0,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_seq_until_any_fail_1,
+ [sequence,{repeat_until_any_fail,2}]},ok}}],
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,
+ repeat_seq_until_any_fail_1,[sequence]},ok}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_2,ok}},
+ {?eh,test_stats,{4,0,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,
+ repeat_seq_until_any_fail_1,[sequence]},ok}}],
+
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_seq_until_any_fail_2,
+ [{repeat_until_any_fail,2},sequence]},ok}},
+ {?eh,test_stats,{5,0,{0,0}}},
+ [{?eh,tc_done,{repeat_1_SUITE,{end_per_group,gr_ok_1,[]},ok}}],
+ {?eh,test_stats,{7,0,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_seq_until_any_fail_2,
+ [{repeat_until_any_fail,2},sequence]},ok}}],
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_seq_until_any_fail_2,[sequence]},
+ ok}},
+ {?eh,test_stats,{8,0,{0,0}}},
+ [{?eh,tc_done,{repeat_1_SUITE,{end_per_group,gr_ok_1,[]},ok}}],
+ {?eh,test_stats,{10,0,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_seq_until_any_fail_2,[sequence]},
+ ok}}],
+
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_seq_until_any_fail_3,
+ [sequence,{repeat_until_any_fail,3}]},ok}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{11,0,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_then_fail_1,ok}},
+ {?eh,test_stats,{12,0,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_2,ok}},
+ {?eh,test_stats,{13,0,{0,0}}},
+ [{?eh,tc_done,{repeat_1_SUITE,{end_per_group,gr_ok_1,[]},ok}}],
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_seq_until_any_fail_3,
+ [sequence,{repeat_until_any_fail,3}]},ok}}],
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_seq_until_any_fail_3,
+ [{repeat_until_any_fail,2},sequence]},ok}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{15,0,{0,0}}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_then_fail_1,
+ {failed,{error,failing_this_time}}}},
+ {?eh,test_stats,{15,1,{0,0}}},
+ {?eh,tc_auto_skip,{repeat_1_SUITE,tc_ok_2,
+ {failed,{repeat_1_SUITE,tc_ok_then_fail_1}}}},
+ {?eh,test_stats,{15,1,{0,1}}},
+ {?eh,tc_auto_skip,{repeat_1_SUITE,tc_ok_1,
+ {failed,{repeat_1_SUITE,tc_ok_then_fail_1}}}},
+ {?eh,test_stats,{15,1,{0,2}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_seq_until_any_fail_3,
+ [{repeat_until_any_fail,2},sequence]},ok}}],
+
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_seq_until_any_fail_4,
+ [{repeat_until_any_fail,3},sequence]},ok}},
+ [{?eh,tc_done,{repeat_1_SUITE,{end_per_group,
+ gr_ok_then_fail_result,[]},ok}}],
+ [{?eh,tc_done,{repeat_1_SUITE,{end_per_group,gr_ok_1,[]},ok}}],
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{18,1,{0,2}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_seq_until_any_fail_4,
+ [{repeat_until_any_fail,3},sequence]},ok}}],
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_seq_until_any_fail_4,
+ [{repeat_until_any_fail,2},sequence]},ok}},
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,gr_ok_then_fail_result,[]},
+ {return_group_result,failed}}}],
+ {?eh,tc_auto_skip,{repeat_1_SUITE,tc_ok_1,
+ {group_result,gr_ok_then_fail_result,failed}}},
+ {?eh,test_stats,{19,1,{0,3}}},
+ {?eh,tc_auto_skip,{repeat_1_SUITE,tc_ok_1,
+ {group_result,gr_ok_then_fail_result,failed}}},
+ {?eh,test_stats,{19,1,{0,4}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_seq_until_any_fail_4,
+ [{repeat_until_any_fail,2},sequence]},ok}}],
+
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_seq_until_any_fail_5,
+ [{repeat_until_any_fail,3},sequence]},ok}},
+ [{?eh,tc_done,{repeat_1_SUITE,{end_per_group,gr_ok_1,[]},ok}}],
+ [{?eh,tc_done,{repeat_1_SUITE,{end_per_group,gr_ok_then_fail_init,[]},ok}}],
+ [{?eh,tc_done,{repeat_1_SUITE,{end_per_group,gr_ok_2,[]},ok}}],
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,test_stats,{23,1,{0,4}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_seq_until_any_fail_5,
+ [{repeat_until_any_fail,3},sequence]},ok}}],
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_seq_until_any_fail_5,
+ [{repeat_until_any_fail,2},sequence]},ok}},
+ [{?eh,tc_done,{repeat_1_SUITE,{end_per_group,gr_ok_1,[]},ok}}],
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,gr_ok_then_fail_init,[]},
+ {failed,{error,failing_this_time}}}},
+ {?eh,test_stats,{24,1,{0,5}}},
+ {?eh,tc_auto_skip,{repeat_1_SUITE,end_per_group,
+ {failed,{repeat_1_SUITE,init_per_group,
+ {'EXIT',failing_this_time}}}}}],
+ {?eh,tc_auto_skip,{repeat_1_SUITE,tc_ok_1,
+ {group_result,gr_ok_then_fail_init,failed}}},
+ {?eh,test_stats,{24,1,{0,6}}},
+ {?eh,tc_auto_skip,{repeat_1_SUITE,tc_ok_1,
+ {group_result,gr_ok_then_fail_init,failed}}},
+ {?eh,test_stats,{24,1,{0,7}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_seq_until_any_fail_5,
+ [{repeat_until_any_fail,2},sequence]},ok}}],
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_seq_until_any_fail,[]},ok}}],
+
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
+%%! Note that when testing shuffled groups, ct_test_support expects
+%%! both the start and done event for cases and init/end_per_group
+test_events(repeat_shuffled_seq_until_any_fail) ->
+ [{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,unknown}},
+
+ [{?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_shuffled_seq_until_any_fail,[]},
+ ok}},
+
+ {shuffle,
+ [{?eh,tc_start,{repeat_1_SUITE,
+ {init_per_group,repeat_shuffled_seq_until_any_fail_1,
+ [{shuffle,'_'},sequence,
+ {repeat_until_any_fail,2}]}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_shuffled_seq_until_any_fail_1,
+ [{shuffle,'_'},sequence,
+ {repeat_until_any_fail,2}]},ok}},
+ {?eh,test_stats,{2,0,{0,0}}},
+ {?eh,tc_start,{repeat_1_SUITE,
+ {end_per_group,repeat_shuffled_seq_until_any_fail_1,
+ [sequence,shuffle,{repeat_until_any_fail,2}]}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_shuffled_seq_until_any_fail_1,
+ [sequence,shuffle,{repeat_until_any_fail,2}]},ok}}]},
+ {shuffle,
+ [{?eh,tc_start,{repeat_1_SUITE,
+ {init_per_group,repeat_shuffled_seq_until_any_fail_1,
+ [{shuffle,'_'},sequence]}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_shuffled_seq_until_any_fail_1,
+ [{shuffle,'_'},sequence]},ok}},
+ {?eh,test_stats,{4,0,{0,0}}},
+ {?eh,tc_start,{repeat_1_SUITE,
+ {end_per_group,repeat_shuffled_seq_until_any_fail_1,
+ [{shuffle,repeated},sequence]}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_shuffled_seq_until_any_fail_1,
+ [{shuffle,repeated},sequence]},ok}}]},
+
+ {shuffle,
+ [{?eh,tc_start,{repeat_1_SUITE,
+ {init_per_group,repeat_shuffled_seq_until_any_fail_2,
+ [{shuffle,{1,2,3}},{repeat_until_any_fail,2},sequence]}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_shuffled_seq_until_any_fail_2,
+ [{shuffle,{1,2,3}},{repeat_until_any_fail,2},sequence]},
+ ok}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_1}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_2}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_2,ok}},
+ [{?eh,tc_start,{repeat_1_SUITE,{end_per_group,gr_ok_1,[]}}},
+ {?eh,tc_done,{repeat_1_SUITE,{end_per_group,gr_ok_1,[]},ok}}],
+ {?eh,test_stats,{7,0,{0,0}}},
+ {?eh,tc_start,{repeat_1_SUITE,
+ {end_per_group,repeat_shuffled_seq_until_any_fail_2,
+ [{repeat_until_any_fail,2},{shuffle,{1,2,3}},sequence]}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_shuffled_seq_until_any_fail_2,
+ [{repeat_until_any_fail,2},{shuffle,{1,2,3}},sequence]},
+ ok}}]},
+ {shuffle,
+ [{?eh,tc_start,{repeat_1_SUITE,
+ {init_per_group,repeat_shuffled_seq_until_any_fail_2,
+ [{shuffle,'_'},sequence]}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_shuffled_seq_until_any_fail_2,
+ [{shuffle,'_'},sequence]},ok}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_1}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_2}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_2,ok}},
+ [{?eh,tc_start,{repeat_1_SUITE,{end_per_group,gr_ok_1,[]}}},
+ {?eh,tc_done,{repeat_1_SUITE,{end_per_group,gr_ok_1,[]},ok}}],
+ {?eh,tc_start,{repeat_1_SUITE,
+ {end_per_group,repeat_shuffled_seq_until_any_fail_2,
+ [{shuffle,repeated},sequence]}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_shuffled_seq_until_any_fail_2,
+ [{shuffle,repeated},sequence]},ok}}]},
+
+ {shuffle,
+ [{?eh,tc_start,{repeat_1_SUITE,
+ {init_per_group,repeat_shuffled_seq_until_any_fail_3,
+ [{shuffle,'_'},sequence,
+ {repeat_until_any_fail,3}]}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_shuffled_seq_until_any_fail_3,
+ [{shuffle,'_'},sequence,
+ {repeat_until_any_fail,3}]},ok}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_then_fail_1}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_then_fail_1,ok}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_1}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_2}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_2,ok}},
+ [{?eh,tc_start,{repeat_1_SUITE,{end_per_group,gr_ok_1,[]}}},
+ {?eh,tc_done,{repeat_1_SUITE,{end_per_group,gr_ok_1,[]},ok}}],
+ {?eh,test_stats,{14,0,{0,0}}},
+ {?eh,tc_start,{repeat_1_SUITE,
+ {end_per_group,repeat_shuffled_seq_until_any_fail_3,
+ [shuffle,sequence,{repeat_until_any_fail,3}]}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_shuffled_seq_until_any_fail_3,
+ [shuffle,sequence,{repeat_until_any_fail,3}]},ok}}]},
+ {shuffle,
+ [{?eh,tc_start,{repeat_1_SUITE,
+ {init_per_group,repeat_shuffled_seq_until_any_fail_3,
+ [{shuffle,'_'},{repeat_until_any_fail,2},sequence]}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_shuffled_seq_until_any_fail_3,
+ [{shuffle,'_'},{repeat_until_any_fail,2},sequence]},
+ ok}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_then_fail_1}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_then_fail_1,
+ {failed,{error,failing_this_time}}}},
+ {?eh,tc_start,{repeat_1_SUITE,
+ {end_per_group,repeat_shuffled_seq_until_any_fail_3,
+ [{shuffle,repeated},{repeat_until_any_fail,2},sequence]}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_shuffled_seq_until_any_fail_3,
+ [{shuffle,repeated},{repeat_until_any_fail,2},sequence]},
+ ok}}]},
+
+ {shuffle,
+ [{?eh,tc_start,{repeat_1_SUITE,
+ {init_per_group,repeat_shuffled_seq_until_any_fail_4,
+ [{shuffle,{1,2,3}},{repeat_until_any_fail,3},sequence]}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_shuffled_seq_until_any_fail_4,
+ [{shuffle,{1,2,3}},{repeat_until_any_fail,3},sequence]},
+ ok}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_1}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ [{?eh,tc_start,{repeat_1_SUITE,{end_per_group,gr_ok_1,[]}}},
+ {?eh,tc_done,{repeat_1_SUITE,{end_per_group,gr_ok_1,[]},ok}}],
+ [{?eh,tc_start,{repeat_1_SUITE,{end_per_group,
+ gr_ok_then_fail_result,[]}}},
+ {?eh,tc_done,{repeat_1_SUITE,{end_per_group,
+ gr_ok_then_fail_result,[]},ok}}],
+ {?eh,tc_start,{repeat_1_SUITE,
+ {end_per_group,repeat_shuffled_seq_until_any_fail_4,
+ [{repeat_until_any_fail,3},sequence,{shuffle,{1,2,3}}]}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_shuffled_seq_until_any_fail_4,
+ [{repeat_until_any_fail,3},sequence,{shuffle,{1,2,3}}]},
+ ok}}]},
+ {shuffle,
+ [{?eh,tc_start,{repeat_1_SUITE,
+ {init_per_group,repeat_shuffled_seq_until_any_fail_4,
+ [{shuffle,'_'},{repeat_until_any_fail,2},sequence]}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_shuffled_seq_until_any_fail_4,
+ [{shuffle,'_'},{repeat_until_any_fail,2},sequence]},
+ ok}},
+ [{?eh,tc_start,{repeat_1_SUITE,
+ {end_per_group,gr_ok_then_fail_result,[]}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,gr_ok_then_fail_result,[]},
+ {return_group_result,failed}}}],
+ {?eh,tc_start,{repeat_1_SUITE,
+ {end_per_group,repeat_shuffled_seq_until_any_fail_4,
+ [{shuffle,repeated},{repeat_until_any_fail,2},sequence]}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_shuffled_seq_until_any_fail_4,
+ [{shuffle,repeated},{repeat_until_any_fail,2},sequence]},
+ ok}}]},
+
+ {shuffle,
+ [{?eh,tc_start,{repeat_1_SUITE,
+ {init_per_group,repeat_shuffled_seq_until_any_fail_5,
+ [{shuffle,{1,2,3}},{repeat_until_any_fail,3},sequence]}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_shuffled_seq_until_any_fail_5,
+ [{shuffle,{1,2,3}},{repeat_until_any_fail,3},sequence]},
+ ok}},
+ {?eh,tc_start,{repeat_1_SUITE,tc_ok_1}},
+ {?eh,tc_done,{repeat_1_SUITE,tc_ok_1,ok}},
+ [{?eh,tc_start,{repeat_1_SUITE,{end_per_group,gr_ok_1,[]}}},
+ {?eh,tc_done,{repeat_1_SUITE,{end_per_group,gr_ok_1,[]},ok}}],
+ [{?eh,tc_start,{repeat_1_SUITE,{end_per_group,gr_ok_2,[]}}},
+ {?eh,tc_done,{repeat_1_SUITE,{end_per_group,gr_ok_2,[]},ok}}],
+ [{?eh,tc_start,{repeat_1_SUITE,{end_per_group,
+ gr_ok_then_fail_init,[]}}},
+ {?eh,tc_done,{repeat_1_SUITE,{end_per_group,
+ gr_ok_then_fail_init,[]},ok}}],
+ {?eh,tc_start,{repeat_1_SUITE,
+ {end_per_group,repeat_shuffled_seq_until_any_fail_5,
+ [{repeat_until_any_fail,3},sequence,{shuffle,{1,2,3}}]}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_shuffled_seq_until_any_fail_5,
+ [{repeat_until_any_fail,3},sequence,{shuffle,{1,2,3}}]},
+ ok}}]},
+ {shuffle,
+ [{?eh,tc_start,{repeat_1_SUITE,
+ {init_per_group,repeat_shuffled_seq_until_any_fail_5,
+ [{shuffle,'_'},{repeat_until_any_fail,2},
+ sequence]}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {init_per_group,repeat_shuffled_seq_until_any_fail_5,
+ [{shuffle,'_'},{repeat_until_any_fail,2},
+ sequence]},ok}},
+ [{?eh,tc_auto_skip,{repeat_1_SUITE,end_per_group,
+ {failed,{repeat_1_SUITE,init_per_group,
+ {'EXIT',failing_this_time}}}}}],
+ {?eh,tc_start,{repeat_1_SUITE,
+ {end_per_group,repeat_shuffled_seq_until_any_fail_5,
+ [{shuffle,repeated},{repeat_until_any_fail,2},sequence]}}},
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_shuffled_seq_until_any_fail_5,
+ [{shuffle,repeated},{repeat_until_any_fail,2},sequence]},
+ ok}}]},
+
+ {?eh,tc_done,{repeat_1_SUITE,
+ {end_per_group,repeat_shuffled_seq_until_any_fail,[]},
+ ok}}],
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}].
diff --git a/lib/common_test/test/ct_repeat_1_SUITE_data/repeat_1_SUITE.erl b/lib/common_test/test/ct_repeat_1_SUITE_data/repeat_1_SUITE.erl
new file mode 100644
index 0000000000..fb8d31edd4
--- /dev/null
+++ b/lib/common_test/test/ct_repeat_1_SUITE_data/repeat_1_SUITE.erl
@@ -0,0 +1,373 @@
+%%%-------------------------------------------------------------------
+%%% @author Peter Andersson <[email protected]>
+%%% @copyright (C) 2010, Peter Andersson
+%%% @doc
+%%%
+%%% @end
+%%% Created : 11 Aug 2010 by Peter Andersson <[email protected]>
+%%%-------------------------------------------------------------------
+-module(repeat_1_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% @spec suite() -> Info
+%% Info = [tuple()]
+%% @end
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,30}}].
+
+%%--------------------------------------------------------------------
+%% @spec init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ spawn(fun() -> db() end),
+ Config.
+%%--------------------------------------------------------------------
+%% @spec end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%% @end
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ db(stop, ok),
+ ok.
+
+db() ->
+ register(?MODULE, self()),
+ db_loop([]).
+
+db_loop(Dict) ->
+ receive
+ {insert,From,Key,Val} ->
+ From ! {?MODULE,ok},
+ db_loop([{Key,Val} | proplists:delete(Key, Dict)]);
+ {lookup,From,Key} ->
+ From ! {?MODULE,proplists:get_value(Key, Dict)},
+ db_loop(Dict);
+ {delete,From,Key} ->
+ From ! {?MODULE,ok},
+ db_loop(proplists:delete(Key, Dict));
+ {stop,From,_} ->
+ From ! {?MODULE,ok}
+ end.
+
+ db(Op, Key, Val) ->
+ ?MODULE ! {Op,self(),Key,Val},
+ receive {?MODULE,Result} -> Result end.
+
+ db(Op, Key) ->
+ ?MODULE ! {Op,self(),Key},
+ receive {?MODULE,Result} -> Result end.
+
+%%--------------------------------------------------------------------
+%% @spec init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+init_per_group(G, Config) when G == gr_ok_1 ; G == gr_ok_2 ;
+ G == gr_fail_result;
+ G == gr_ok_then_fail_result ->
+ ct:comment(G),
+ Config;
+
+init_per_group(G, _Config) when G == gr_fail_init ->
+ ct:comment(G),
+ exit(fails_on_purpose);
+
+init_per_group(G, Config) when G == gr_ok_then_fail_init ->
+ ct:comment(G),
+ do_2nd_time(G,
+ fun() -> exit(failing_this_time) end,
+ fun() -> Config end);
+
+init_per_group(G, Config) when G == gr_fail_init_then_ok ->
+ ct:comment(G),
+ do_2nd_time(G,
+ fun() -> Config end,
+ fun() -> exit(failing_this_time) end);
+
+init_per_group(G, Config) ->
+ ct:comment(G),
+ Config.
+
+%%--------------------------------------------------------------------
+%% @spec end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% @end
+%%--------------------------------------------------------------------
+end_per_group(G, _Config) when G == gr_fail_result ->
+ ct:comment(G),
+ {return_group_result,failed};
+
+end_per_group(G, _Config) when G == gr_ok_then_fail_result ->
+ ct:comment(G),
+ do_2nd_time(G,
+ fun() -> {return_group_result,failed} end,
+ fun() -> ok end);
+
+end_per_group(G, _Config) when G == gr_fail_result_then_ok ->
+ ct:comment(G),
+ do_2nd_time(G,
+ fun() -> ok end,
+ fun() -> {return_group_result,failed} end);
+
+end_per_group(G, _Config) ->
+ ct:comment(G),
+ ok.
+
+%%--------------------------------------------------------------------
+%% @spec init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% @spec end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1} | {fail,Reason}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% @spec groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%% @end
+%%--------------------------------------------------------------------
+groups() ->
+ [
+ %%---------------------------------------------------------------
+ {repeat_cs, [], [{group,repeat_cs_0},
+ {group,repeat_cs_1},
+ {group,repeat_cs_2}]},
+ {repeat_cs_0, [{repeat,0}], [tc_ok_1,tc_ok_2]},
+ {repeat_cs_1, [{repeat,1}], [tc_ok_1,tc_ok_2]},
+ {repeat_cs_2, [{repeat,2}], [tc_ok_1,tc_ok_2]},
+
+ {repeat_cs_and_grs, [{repeat,2}], [{group,gr_ok_1},tc_fail_1,
+ {group,gr_fail_result},tc_ok_1,
+ {group,gr_fail_init},tc_ok_2]},
+
+ %%---------------------------------------------------------------
+ {repeat_seq, [], [{group,repeat_seq_1},
+ {group,repeat_seq_2},
+ {group,repeat_seq_3},
+ {group,repeat_seq_4}]},
+ {repeat_seq_1, [sequence,{repeat,2}], [tc_ok_1,tc_fail_1,tc_ok_2]},
+ {repeat_seq_2, [sequence,{repeat,2}], [tc_ok_1,{group,gr_fail_result},tc_ok_2]},
+ {repeat_seq_3, [sequence,{repeat,2}], [tc_ok_1,{group,gr_fail_init},tc_ok_2]},
+ {repeat_seq_4, [sequence,{repeat,2}], [tc_fail_1,{group,gr_ok_1},tc_ok_1]},
+
+ %%---------------------------------------------------------------
+ {repeat_cs_until_any_ok, [], [{group,repeat_cs_until_any_ok_1},
+ {group,repeat_cs_until_any_ok_2}]},
+ {repeat_cs_until_any_ok_1, [{repeat_until_any_ok,3}], [tc_fail_1,
+ tc_fail_2,
+ tc_fail_then_ok_1]},
+ {repeat_cs_until_any_ok_2, [{repeat_until_any_ok,3}], [tc_ok_1,tc_fail_1]},
+
+ %%---------------------------------------------------------------
+ {repeat_gr_until_any_ok, [], [{group,repeat_gr_until_any_ok_1},
+ {group,repeat_gr_until_any_ok_2}]},
+ {repeat_gr_until_any_ok_1, [{repeat_until_any_ok,3}],
+ [{group,gr_fail_result}, tc_fail_1, {group,gr_fail_init}, tc_fail_2,
+ {group,gr_fail_result_then_ok}]},
+ {repeat_gr_until_any_ok_2, [{repeat_until_any_ok,3}],
+ [{group,gr_fail_result}, tc_fail_1, tc_fail_then_ok_1,
+ {group,gr_fail_init}]},
+
+ %%---------------------------------------------------------------
+ {repeat_cs_until_any_fail, [], [{group,repeat_cs_until_any_fail_1},
+ {group,repeat_cs_until_any_fail_2}]},
+ {repeat_cs_until_any_fail_1, [{repeat_until_any_fail,3}], [tc_ok_1,
+ tc_ok_2,
+ tc_ok_then_fail_1]},
+ {repeat_cs_until_any_fail_2, [{repeat_until_any_fail,3}], [tc_fail_1,tc_fail_2]},
+
+ %%---------------------------------------------------------------
+ {repeat_gr_until_any_fail, [], [{group,repeat_gr_until_any_fail_1},
+ {group,repeat_gr_until_any_fail_2},
+ {group,repeat_gr_until_any_fail_3}]},
+ {repeat_gr_until_any_fail_1, [{repeat_until_any_fail,3}],
+ [{group,gr_ok_1}, tc_ok_1, {group,gr_ok_then_fail_result}, tc_ok_2]},
+ {repeat_gr_until_any_fail_2, [{repeat_until_any_fail,3}],
+ [{group,gr_ok_1}, tc_ok_1, {group,gr_ok_then_fail_init}, tc_ok_2]},
+ {repeat_gr_until_any_fail_3, [{repeat_until_any_fail,3}], [tc_ok_then_fail_1,
+ {group,gr_ok_1},
+ tc_ok_1]},
+
+ %%---------------------------------------------------------------
+ {repeat_cs_until_all_ok, [], [{group,repeat_cs_until_all_ok_1},
+ {group,repeat_cs_until_all_ok_2}]},
+ {repeat_cs_until_all_ok_1, [{repeat_until_all_ok,3}], [tc_fail_then_ok_1,
+ tc_ok_1,
+ tc_fail_then_ok_2]},
+ {repeat_cs_until_all_ok_2, [{repeat_until_all_ok,3}], [tc_ok_1,tc_ok_2]},
+
+ %%---------------------------------------------------------------
+ {repeat_gr_until_all_ok, [], [{group,repeat_gr_until_all_ok_1},
+ {group,repeat_gr_until_all_ok_2},
+ {group,repeat_gr_until_all_ok_3}]},
+ {repeat_gr_until_all_ok_1, [{repeat_until_all_ok,3}],
+ [tc_ok_1, {group,gr_ok_1}, tc_fail_then_ok_1, {group,gr_fail_result_then_ok}]},
+ {repeat_gr_until_all_ok_2, [{repeat_until_all_ok,3}],
+ [{group,gr_fail_init_then_ok}, tc_ok_1]},
+ {repeat_gr_until_all_ok_3, [{repeat_until_all_ok,3}],
+ [{group,gr_ok_1}, tc_fail_then_ok_1]},
+
+ %%---------------------------------------------------------------
+ {repeat_cs_until_all_fail, [], [{group,repeat_cs_until_all_fail_1},
+ {group,repeat_cs_until_all_fail_2}]},
+ {repeat_cs_until_all_fail_1, [{repeat_until_all_fail,3}], [tc_ok_then_fail_1,
+ tc_fail_1,
+ tc_ok_then_fail_2]},
+ {repeat_cs_until_all_fail_2, [{repeat_until_all_fail,3}], [tc_fail_1]},
+
+ %%---------------------------------------------------------------
+ {repeat_gr_until_all_fail, [], [{group,repeat_gr_until_all_fail_1},
+ {group,repeat_gr_until_all_fail_2},
+ {group,repeat_gr_until_all_fail_3}]},
+ {repeat_gr_until_all_fail_1, [{repeat_until_all_fail,3}],
+ [tc_fail_1, {group,gr_fail_init}, tc_ok_then_fail_1, {group,gr_ok_then_fail_result}]},
+ {repeat_gr_until_all_fail_2, [{repeat_until_all_fail,3}],
+ [{group,gr_ok_then_fail_init}, tc_fail_1]},
+ {repeat_gr_until_all_fail_3, [{repeat_until_all_fail,3}],
+ [{group,gr_fail_result}, tc_ok_then_fail_1]},
+
+ %%---------------------------------------------------------------
+ {repeat_seq_until_any_fail, [], [{group,repeat_seq_until_any_fail_1},
+ {group,repeat_seq_until_any_fail_2},
+ {group,repeat_seq_until_any_fail_3},
+ {group,repeat_seq_until_any_fail_4},
+ {group,repeat_seq_until_any_fail_5}]},
+ {repeat_seq_until_any_fail_1, [sequence,{repeat_until_any_fail,2}],
+ [tc_ok_1, tc_ok_2]},
+ {repeat_seq_until_any_fail_2, [{repeat_until_any_fail,2},sequence],
+ [tc_ok_1, {group,gr_ok_1}, tc_ok_2]},
+ {repeat_seq_until_any_fail_3, [sequence,{repeat_until_any_fail,3}],
+ [tc_ok_1, tc_ok_then_fail_1, tc_ok_2, {group,gr_ok_1}]},
+ {repeat_seq_until_any_fail_4, [{repeat_until_any_fail,3},sequence],
+ [{group,gr_ok_then_fail_result}, {group,gr_ok_1}, tc_ok_1]},
+ {repeat_seq_until_any_fail_5, [{repeat_until_any_fail,3},sequence],
+ [{group,gr_ok_1}, {group,gr_ok_then_fail_init}, {group,gr_ok_2}, tc_ok_1]},
+
+ %%---------------------------------------------------------------
+ {repeat_shuffled_seq_until_any_fail, [], [{group,repeat_shuffled_seq_until_any_fail_1},
+ {group,repeat_shuffled_seq_until_any_fail_2},
+ {group,repeat_shuffled_seq_until_any_fail_3},
+ {group,repeat_shuffled_seq_until_any_fail_4},
+ {group,repeat_shuffled_seq_until_any_fail_5}]},
+ {repeat_shuffled_seq_until_any_fail_1, [sequence,shuffle,{repeat_until_any_fail,2}],
+ [tc_ok_1, tc_ok_2]},
+ {repeat_shuffled_seq_until_any_fail_2, [{repeat_until_any_fail,2},{shuffle,{1,2,3}},sequence],
+ [tc_ok_1, {group,gr_ok_1}, tc_ok_2]},
+ {repeat_shuffled_seq_until_any_fail_3, [shuffle,sequence,{repeat_until_any_fail,3}],
+ [tc_ok_1, tc_ok_then_fail_1, tc_ok_2, {group,gr_ok_1}]},
+ {repeat_shuffled_seq_until_any_fail_4, [{repeat_until_any_fail,3},sequence,{shuffle,{1,2,3}}],
+ [{group,gr_ok_then_fail_result}, {group,gr_ok_1}, tc_ok_1]},
+ {repeat_shuffled_seq_until_any_fail_5, [{repeat_until_any_fail,3},sequence,{shuffle,{1,2,3}}],
+ [{group,gr_ok_1}, {group,gr_ok_then_fail_init}, {group,gr_ok_2}, tc_ok_1]},
+
+ %%---------------------------------------------------------------
+ {gr_ok_1, [], [tc_ok_1]},
+
+ {gr_ok_2, [], [tc_ok_1]},
+
+ {gr_fail_init, [], [tc_ok_1]},
+
+ {gr_fail_result, [], [tc_ok_1]},
+
+ {gr_ok_then_fail_init, [], [tc_ok_1]},
+
+ {gr_ok_then_fail_result, [], [tc_ok_1]},
+
+ {gr_fail_result_then_ok, [], [tc_ok_1]},
+
+ {gr_fail_init_then_ok, [], [tc_ok_1]}
+ ].
+
+%%--------------------------------------------------------------------
+%% @spec all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+all() ->
+ [].
+
+tc_ok_1(_) ->
+ ok.
+
+tc_ok_2(_) ->
+ ok.
+
+tc_fail_1(_) ->
+ x=2.
+
+tc_fail_2(_) ->
+ exit(exit_on_purpose).
+
+tc_ok_then_fail_1(_) ->
+ do_2nd_time(tc_ok_then_fail_1,
+ fun() -> exit(failing_this_time) end,
+ fun() -> ok end),
+ ok.
+
+tc_ok_then_fail_2(_) ->
+ do_2nd_time(tc_ok_then_fail_2,
+ fun() -> exit(failing_this_time) end,
+ fun() -> ok end),
+ ok.
+
+tc_fail_then_ok_1(_) ->
+ do_2nd_time(tc_fail_then_ok_1,
+ fun() -> ok end,
+ fun() -> exit(failing_this_time) end),
+ ok.
+
+tc_fail_then_ok_2(_) ->
+ do_2nd_time(tc_fail_then_ok_2,
+ fun() -> ok end,
+ fun() -> exit(failing_this_time) end),
+ ok.
+
+do_2nd_time(Case, True, False) ->
+ case db(lookup, Case) of
+ undefined ->
+ db(insert, Case, 1),
+ False();
+ 1 ->
+ ct:log("This is the second call...", []),
+ db(delete, Case),
+ True()
+ end.
diff --git a/lib/common_test/test/ct_sequence_1_SUITE.erl b/lib/common_test/test/ct_sequence_1_SUITE.erl
new file mode 100644
index 0000000000..0cf40f106a
--- /dev/null
+++ b/lib/common_test/test/ct_sequence_1_SUITE.erl
@@ -0,0 +1,300 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%%-------------------------------------------------------------------
+%%% File: ct_sequence_1_SUITE
+%%%
+%%% Description:
+%%% Test sequences
+%%%
+%%% The suites used for the test are located in the data directory.
+%%%-------------------------------------------------------------------
+-module(ct_sequence_1_SUITE).
+
+-compile(export_all).
+
+-include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+
+-define(eh, ct_test_support_eh).
+
+%%--------------------------------------------------------------------
+%% TEST SERVER CALLBACK FUNCTIONS
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% Description: Since Common Test starts another Test Server
+%% instance, the tests need to be performed on a separate node (or
+%% there will be clashes with logging processes etc).
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config1 = ct_test_support:init_per_suite(Config),
+ Config1.
+
+end_per_suite(Config) ->
+ ct_test_support:end_per_suite(Config).
+
+init_per_testcase(TestCase, Config) ->
+ ct_test_support:init_per_testcase(TestCase, Config).
+
+end_per_testcase(TestCase, Config) ->
+ ct_test_support:end_per_testcase(TestCase, Config).
+
+all(suite) ->
+ [subgroup_return_fail,
+ subgroup_init_fail,
+ subgroup_after_failed_case,
+ case_after_subgroup_return_fail,
+ case_after_subgroup_fail_init].
+
+%%--------------------------------------------------------------------
+%% TEST CASES
+%%--------------------------------------------------------------------
+
+%%%-----------------------------------------------------------------
+%%%
+
+subgroup_return_fail(Config) when is_list(Config) ->
+ execute(subgroup_return_fail,
+ "subgroups_1_SUITE", subgroup_return_fail,
+ Config).
+
+%%%-----------------------------------------------------------------
+%%%
+
+subgroup_init_fail(Config) when is_list(Config) ->
+ execute(subgroup_init_fail,
+ "subgroups_1_SUITE", subgroup_init_fail,
+ Config).
+
+%%%-----------------------------------------------------------------
+%%%
+
+subgroup_after_failed_case(Config) when is_list(Config) ->
+ execute(subgroup_after_failed_case,
+ "subgroups_1_SUITE", subgroup_after_failed_case,
+ Config).
+
+%%%-----------------------------------------------------------------
+%%%
+
+case_after_subgroup_return_fail(Config) when is_list(Config) ->
+ execute(case_after_subgroup_return_fail,
+ "subgroups_1_SUITE", case_after_subgroup_return_fail,
+ Config).
+
+%%%-----------------------------------------------------------------
+%%%
+
+case_after_subgroup_fail_init(Config) when is_list(Config) ->
+ execute(case_after_subgroup_fail_init,
+ "subgroups_1_SUITE", case_after_subgroup_fail_init,
+ Config).
+
+%%%-----------------------------------------------------------------
+%%% HELP FUNCTIONS
+%%%-----------------------------------------------------------------
+
+execute(TestCase, SuiteName, Group, Config) ->
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join(DataDir, SuiteName),
+
+ {Opts,ERPid} = setup([{suite,Suite},{group,Group},{label,TestCase}], Config),
+ ok = ct_test_support:run(Opts, Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(TestCase,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config)),
+
+ TestEvents = events_to_check(TestCase),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+setup(Test, Config) ->
+ Opts0 = ct_test_support:get_opts(Config),
+ Level = ?config(trace_level, Config),
+ EvHArgs = [{cbm,ct_test_support},{trace_level,Level}],
+ Opts = Opts0 ++ [{event_handler,{?eh,EvHArgs}} | Test],
+ ERPid = ct_test_support:start_event_receiver(Config),
+ {Opts,ERPid}.
+
+reformat(Events, EH) ->
+ ct_test_support:reformat(Events, EH).
+%reformat(Events, _EH) ->
+% Events.
+
+%%%-----------------------------------------------------------------
+%%% TEST EVENTS
+%%%-----------------------------------------------------------------
+events_to_check(Test) ->
+ %% 2 tests (ct:run_test + script_start) is default
+ events_to_check(Test, 2).
+
+events_to_check(_, 0) ->
+ [];
+events_to_check(Test, N) ->
+ test_events(Test) ++ events_to_check(Test, N-1).
+
+test_events(subgroup_return_fail) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,2}},
+ [{?eh,tc_start,
+ {subgroups_1_SUITE,{init_per_group,subgroup_return_fail,[sequence]}}},
+ {?eh,tc_done,
+ {subgroups_1_SUITE,{init_per_group,subgroup_return_fail,[sequence]},ok}},
+ [{?eh,tc_start,
+ {subgroups_1_SUITE,{init_per_group,return_fail,[]}}},
+ {?eh,tc_done,
+ {subgroups_1_SUITE,{init_per_group,return_fail,[]},ok}},
+ {?eh,tc_start,{subgroups_1_SUITE,failing_tc}},
+ {?eh,tc_done,
+ {subgroups_1_SUITE,failing_tc,{failed,{error,{{badmatch,3},'_'}}}}},
+ {?eh,test_stats,{0,1,{0,0}}},
+ {?eh,tc_start,
+ {subgroups_1_SUITE,{end_per_group,return_fail,[]}}},
+ {?eh,tc_done,{subgroups_1_SUITE,{end_per_group,return_fail,[]},
+ {return_group_result,failed}}}],
+ {?eh,tc_auto_skip,
+ {subgroups_1_SUITE,ok_tc,{group_result,return_fail,failed}}},
+ {?eh,test_stats,{0,1,{0,1}}},
+ {?eh,tc_start,
+ {subgroups_1_SUITE,{end_per_group,subgroup_return_fail,[sequence]}}},
+ {?eh,tc_done,
+ {subgroups_1_SUITE,{end_per_group,subgroup_return_fail,[sequence]},
+ {return_group_result,failed}}}],
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(subgroup_init_fail) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,2}},
+ [{?eh,tc_start,
+ {subgroups_1_SUITE,{init_per_group,subgroup_init_fail,[sequence]}}},
+ {?eh,tc_done,
+ {subgroups_1_SUITE,{init_per_group,subgroup_init_fail,[sequence]},ok}},
+ [{?eh,tc_start,{subgroups_1_SUITE,{init_per_group,fail_init,[]}}},
+ {?eh,tc_done,{subgroups_1_SUITE,{init_per_group,fail_init,[]},
+ {failed,{error,init_per_group_fails_on_purpose}}}},
+ {?eh,tc_auto_skip,{subgroups_1_SUITE,ok_tc,
+ {failed,{subgroups_1_SUITE,init_per_group,
+ {'EXIT',init_per_group_fails_on_purpose}}}}},
+ {?eh,test_stats,{0,0,{0,1}}},
+ {?eh,tc_auto_skip,{subgroups_1_SUITE,end_per_group,
+ {failed,{subgroups_1_SUITE,init_per_group,
+ {'EXIT',init_per_group_fails_on_purpose}}}}}],
+ {?eh,tc_auto_skip,{subgroups_1_SUITE,ok_tc,{group_result,fail_init,failed}}},
+ {?eh,test_stats,{0,0,{0,2}}},
+ {?eh,tc_start,{subgroups_1_SUITE,{end_per_group,subgroup_init_fail,[sequence]}}},
+ {?eh,tc_done,{subgroups_1_SUITE,
+ {end_per_group,subgroup_init_fail,[sequence]},
+ {return_group_result,failed}}}],
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(subgroup_after_failed_case) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,2}},
+ [{?eh,tc_start,{subgroups_1_SUITE,
+ {init_per_group,subgroup_after_failed_case,[sequence]}}},
+ {?eh,tc_done,{subgroups_1_SUITE,
+ {init_per_group,subgroup_after_failed_case,[sequence]},ok}},
+ {?eh,tc_start,{subgroups_1_SUITE,failing_tc}},
+ {?eh,tc_done,{subgroups_1_SUITE,failing_tc,{failed,{error,{{badmatch,3},'_'}}}}},
+ {?eh,test_stats,{0,1,{0,0}}},
+ {?eh,tc_auto_skip,{subgroups_1_SUITE,ok_tc,{failed,{subgroups_1_SUITE,failing_tc}}}},
+ {?eh,test_stats,{0,1,{0,1}}},
+ {?eh,tc_start,{subgroups_1_SUITE,
+ {end_per_group,subgroup_after_failed_case,[sequence]}}},
+ {?eh,tc_done,{subgroups_1_SUITE,
+ {end_per_group,subgroup_after_failed_case,[sequence]},
+ {return_group_result,failed}}}],
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+];
+
+test_events(case_after_subgroup_return_fail) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,2}},
+ [{?eh,tc_start,{subgroups_1_SUITE,
+ {init_per_group,case_after_subgroup_return_fail,[sequence]}}},
+ {?eh,tc_done,{subgroups_1_SUITE,
+ {init_per_group,case_after_subgroup_return_fail,[sequence]},ok}},
+ [{?eh,tc_start,{subgroups_1_SUITE,{init_per_group,return_fail,[]}}},
+ {?eh,tc_done,{subgroups_1_SUITE,{init_per_group,return_fail,[]},ok}},
+ {?eh,tc_start,{subgroups_1_SUITE,failing_tc}},
+ {?eh,tc_done,{subgroups_1_SUITE,failing_tc,{failed,{error,{{badmatch,3},'_'}}}}},
+ {?eh,test_stats,{0,1,{0,0}}},
+ {?eh,tc_start,{subgroups_1_SUITE,{end_per_group,return_fail,[]}}},
+ {?eh,tc_done,{subgroups_1_SUITE,{end_per_group,return_fail,[]},
+ {return_group_result,failed}}}],
+ {?eh,tc_auto_skip,{subgroups_1_SUITE,ok_tc,{group_result,return_fail,failed}}},
+ {?eh,test_stats,{0,1,{0,1}}},
+ {?eh,tc_start,{subgroups_1_SUITE,
+ {end_per_group,case_after_subgroup_return_fail,[sequence]}}},
+ {?eh,tc_done,{subgroups_1_SUITE,
+ {end_per_group,case_after_subgroup_return_fail,[sequence]},
+ {return_group_result,failed}}}],
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(case_after_subgroup_fail_init) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,2}},
+ [{?eh,tc_start,{subgroups_1_SUITE,
+ {init_per_group,case_after_subgroup_fail_init,[sequence]}}},
+ {?eh,tc_done,{subgroups_1_SUITE,
+ {init_per_group,case_after_subgroup_fail_init,[sequence]},ok}},
+ [{?eh,tc_start,{subgroups_1_SUITE,{init_per_group,fail_init,[]}}},
+ {?eh,tc_done,{subgroups_1_SUITE,
+ {init_per_group,fail_init,[]},
+ {failed,{error,init_per_group_fails_on_purpose}}}},
+ {?eh,tc_auto_skip,{subgroups_1_SUITE,ok_tc,
+ {failed,
+ {subgroups_1_SUITE,init_per_group,
+ {'EXIT',init_per_group_fails_on_purpose}}}}},
+ {?eh,test_stats,{0,0,{0,1}}},
+ {?eh,tc_auto_skip,{subgroups_1_SUITE,end_per_group,
+ {failed,
+ {subgroups_1_SUITE,init_per_group,
+ {'EXIT',init_per_group_fails_on_purpose}}}}}],
+
+ {?eh,tc_auto_skip,
+ {subgroups_1_SUITE,ok_tc,{group_result,fail_init,failed}}},
+ {?eh,test_stats,{0,0,{0,2}}},
+ {?eh,tc_start,{subgroups_1_SUITE,
+ {end_per_group,case_after_subgroup_fail_init,[sequence]}}},
+ {?eh,tc_done,{subgroups_1_SUITE,
+ {end_per_group,case_after_subgroup_fail_init,[sequence]},
+ {return_group_result,failed}}}],
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ].
diff --git a/lib/common_test/test/ct_sequence_1_SUITE_data/subgroups_1_SUITE.erl b/lib/common_test/test/ct_sequence_1_SUITE_data/subgroups_1_SUITE.erl
new file mode 100644
index 0000000000..741b1165c1
--- /dev/null
+++ b/lib/common_test/test/ct_sequence_1_SUITE_data/subgroups_1_SUITE.erl
@@ -0,0 +1,108 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(subgroups_1_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+all() ->
+ [{group, subgroup_return_fail},
+ {group, subgroup_init_fail},
+ {group, subgroup_after_failed_case},
+ {group, case_after_subgroup_return_fail},
+ {group, case_after_subgroup_fail_init}].
+
+groups() ->
+ [{return_fail, [], [failing_tc]},
+ {fail_init, [], [ok_tc]},
+ {ok_group, [], [ok_tc]},
+
+ {subgroup_return_fail, [sequence], [{group, return_fail}, {group, ok_group}]},
+
+ {subgroup_init_fail, [sequence], [{group, fail_init}, {group, ok_group}]},
+
+ {subgroup_after_failed_case, [sequence], [failing_tc, {group, ok_group}]},
+
+ {case_after_subgroup_return_fail, [sequence], [{group, return_fail}, ok_tc]},
+
+ {case_after_subgroup_fail_init, [sequence], [{group, fail_init}, ok_tc]}
+ ].
+
+failed_subgroup(subgroup_return_fail) -> return_fail;
+failed_subgroup(subgroup_init_fail) -> fail_init;
+failed_subgroup(case_after_subgroup_return_fail) -> return_fail;
+failed_subgroup(case_after_subgroup_fail_init) -> fail_init;
+failed_subgroup(_) -> undefined.
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(fail_init, Config) ->
+ ct:comment(fail_init),
+ exit(init_per_group_fails_on_purpose);
+
+init_per_group(Group, Config) ->
+ ct:comment(Group),
+ [{Group,failed_subgroup(Group)} | Config].
+
+end_per_group(subgroup_after_failed_case, Config) ->
+ ct:comment(subgroup_after_failed_case),
+ Status = ?config(tc_group_result, Config),
+ [{subgroups_1_SUITE,failing_tc}] = proplists:get_value(failed, Status),
+ {return_group_result,failed};
+
+end_per_group(Group, Config) when Group == subgroup_return_fail;
+ Group == subgroup_init_fail;
+ Group == case_after_subgroup_return_fail;
+ Group == case_after_subgroup_fail_init ->
+ ct:comment(Group),
+ Status = ?config(tc_group_result, Config),
+ Failed = proplists:get_value(failed, Status),
+ true = lists:member({group_result,?config(Group,Config)}, Failed),
+ {return_group_result,failed};
+
+end_per_group(return_fail, Config) ->
+ ct:comment(return_fail),
+ Status = ?config(tc_group_result, Config),
+ [{subgroups_1_SUITE,failing_tc}] = proplists:get_value(failed, Status),
+ {return_group_result,failed};
+
+end_per_group(Group, _Config) ->
+ ct:comment(Group),
+ ok.
+
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+end_per_testcase(failing_tc, Config) ->
+ {failed,_} = proplists:get_value(tc_status, Config),
+ ok;
+
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+failing_tc(_Config) ->
+ 2=3.
+
+ok_tc(_Config) ->
+ ok.
diff --git a/lib/compiler/doc/src/notes.xml b/lib/compiler/doc/src/notes.xml
index c08839bc7b..00ea0da55c 100644
--- a/lib/compiler/doc/src/notes.xml
+++ b/lib/compiler/doc/src/notes.xml
@@ -31,6 +31,21 @@
<p>This document describes the changes made to the Compiler
application.</p>
+<section><title>Compiler 4.7.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Eliminated warnings for auto-imported BIF clashes.</p>
+ <p>
+ Own Id: OTP-8840</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Compiler 4.7</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/compiler/src/beam_block.erl b/lib/compiler/src/beam_block.erl
index 9c6f835ab0..c45874597a 100644
--- a/lib/compiler/src/beam_block.erl
+++ b/lib/compiler/src/beam_block.erl
@@ -36,12 +36,13 @@ function({function,Name,Arity,CLabel,Is0}, Lc0) ->
%% Collect basic blocks and optimize them.
Is2 = blockify(Is1),
- Is3 = beam_utils:live_opt(Is2),
- Is4 = opt_blocks(Is3),
- Is5 = beam_utils:delete_live_annos(Is4),
+ Is3 = move_allocates(Is2),
+ Is4 = beam_utils:live_opt(Is3),
+ Is5 = opt_blocks(Is4),
+ Is6 = beam_utils:delete_live_annos(Is5),
%% Optimize bit syntax.
- {Is,Lc} = bsm_opt(Is5, Lc0),
+ {Is,Lc} = bsm_opt(Is6, Lc0),
%% Done.
{{function,Name,Arity,CLabel,Is},Lc}
@@ -156,11 +157,7 @@ opt_blocks([I|Is]) ->
opt_blocks([]) -> [].
opt_block(Is0) ->
- %% We explicitly move any allocate instruction upwards before optimising
- %% moves, to avoid any potential problems with the calculation of live
- %% registers.
- Is1 = move_allocates(Is0),
- Is = find_fixpoint(fun opt/1, Is1),
+ Is = find_fixpoint(fun opt/1, Is0),
opt_alloc(Is).
find_fixpoint(OptFun, Is0) ->
@@ -170,11 +167,21 @@ find_fixpoint(OptFun, Is0) ->
end.
%% move_allocates(Is0) -> Is
-%% Move allocates upwards in the instruction stream, in the hope of
-%% getting more possibilities for optimizing away moves later.
-
-move_allocates(Is) ->
- move_allocates_1(reverse(Is), []).
+%% Move allocate instructions upwards in the instruction stream, in the
+%% hope of getting more possibilities for optimizing away moves later.
+%%
+%% NOTE: Moving allocation instructions is only safe because it is done
+%% immediately after code generation so that we KNOW that if {x,X} is
+%% initialized, all x registers with lower numbers are also initialized.
+%% That assumption may not be true after other optimizations, such as
+%% the beam_utils:live_opt/1 optimization.
+
+move_allocates([{block,Bl0}|Is]) ->
+ Bl = move_allocates_1(reverse(Bl0), []),
+ [{block,Bl}|move_allocates(Is)];
+move_allocates([I|Is]) ->
+ [I|move_allocates(Is)];
+move_allocates([]) -> [].
move_allocates_1([{set,[],[],{alloc,_,_}=Alloc}|Is0], Acc0) ->
{Is,Acc} = move_allocates_2(Alloc, Is0, Acc0),
diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl
index f3a2b01e04..fb267b35b6 100644
--- a/lib/compiler/src/beam_validator.erl
+++ b/lib/compiler/src/beam_validator.erl
@@ -20,6 +20,8 @@
-compile({no_auto_import,[min/2]}).
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([file/1, files/1]).
%% Interface for compiler.
diff --git a/lib/compiler/src/cerl.erl b/lib/compiler/src/cerl.erl
index d1fd9d40e2..4b74d60e9f 100644
--- a/lib/compiler/src/cerl.erl
+++ b/lib/compiler/src/cerl.erl
@@ -973,7 +973,7 @@ atom_name(Node) ->
%% TODO: replace the use of the unofficial 'write_string/2'.
--spec atom_lit(cerl()) -> string().
+-spec atom_lit(cerl()) -> nonempty_string().
atom_lit(Node) ->
io_lib:write_string(atom_name(Node), $'). %' stupid Emacs.
@@ -1079,7 +1079,7 @@ char_val(Node) ->
%%
%% @see c_char/1
--spec char_lit(c_literal()) -> string().
+-spec char_lit(c_literal()) -> nonempty_string().
char_lit(Node) ->
io_lib:write_char(char_val(Node)).
@@ -1178,7 +1178,7 @@ string_val(Node) ->
%%
%% @see c_string/1
--spec string_lit(c_literal()) -> string().
+-spec string_lit(c_literal()) -> nonempty_string().
string_lit(Node) ->
io_lib:write_string(string_val(Node)).
diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl
index ed7a9144a8..26da3ecad2 100644
--- a/lib/compiler/src/compile.erl
+++ b/lib/compiler/src/compile.erl
@@ -824,6 +824,10 @@ foldl_transform(St, [T|Ts]) ->
{'EXIT',R} ->
Es = [{St#compile.ifile,[{none,compile,{parse_transform,T,R}}]}],
{error,St#compile{errors=St#compile.errors ++ Es}};
+ {warning, Forms, Ws} ->
+ foldl_transform(
+ St#compile{code=Forms,
+ warnings=St#compile.warnings ++ Ws}, Ts);
Forms ->
foldl_transform(St#compile{code=Forms}, Ts)
end;
diff --git a/lib/compiler/src/core_lint.erl b/lib/compiler/src/core_lint.erl
index b633f568c9..b513a8965c 100644
--- a/lib/compiler/src/core_lint.erl
+++ b/lib/compiler/src/core_lint.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -65,7 +65,8 @@
| {'return_mismatch', fa()} | {'undefined_function', fa()}
| {'duplicate_var', cerl:var_name(), fa()}
| {'unbound_var', cerl:var_name(), fa()}
- | {'undefined_function', fa(), fa()}.
+ | {'undefined_function', fa(), fa()}
+ | {'tail_segment_not_at_end', fa()}.
-type error() :: {module(), err_desc()}.
-type warning() :: {module(), term()}.
@@ -116,7 +117,9 @@ format_error({duplicate_var,N,{F,A}}) ->
format_error({unbound_var,N,{F,A}}) ->
io_lib:format("unbound variable ~s in ~w/~w", [N,F,A]);
format_error({undefined_function,{F1,A1},{F2,A2}}) ->
- io_lib:format("undefined function ~w/~w in ~w/~w", [F1,A1,F2,A2]).
+ io_lib:format("undefined function ~w/~w in ~w/~w", [F1,A1,F2,A2]);
+format_error({tail_segment_not_at_end,{F,A}}) ->
+ io_lib:format("binary tail segment not at end in ~w/~w", [F,A]).
-type ret() :: {'ok', [{module(), [warning(),...]}]}
| {'error', [{module(), [error(),...]}],
@@ -450,7 +453,8 @@ pattern(#c_cons{hd=H,tl=T}, Def, Ps, St) ->
pattern_list([H,T], Def, Ps, St);
pattern(#c_tuple{es=Es}, Def, Ps, St) ->
pattern_list(Es, Def, Ps, St);
-pattern(#c_binary{segments=Ss}, Def, Ps, St) ->
+pattern(#c_binary{segments=Ss}, Def, Ps, St0) ->
+ St = pat_bin_tail_check(Ss, St0),
pat_bin(Ss, Def, Ps, St);
pattern(#c_alias{var=V,pat=P}, Def, Ps, St0) ->
{Vvs,St1} = variable(V, Ps, St0),
@@ -482,6 +486,19 @@ pat_segment(#c_bitstr{val=V,size=S,type=T}, Def0, Ps0, St0) ->
pat_segment(_, Def, Ps, St) ->
{Ps,Def,add_error({not_bs_pattern,St#lint.func}, St)}.
+%% pat_bin_tail_check([Elem], State) -> State.
+%% There must be at most one tail segment (a size-less segment of
+%% type binary) and it must occur at the end.
+
+pat_bin_tail_check([#c_bitstr{size=#c_literal{val=all}}], St) ->
+ %% Size-less field is OK at the end of the list of segments.
+ St;
+pat_bin_tail_check([#c_bitstr{size=#c_literal{val=all}}|_], St) ->
+ add_error({tail_segment_not_at_end,St#lint.func}, St);
+pat_bin_tail_check([_|Ss], St) ->
+ pat_bin_tail_check(Ss, St);
+pat_bin_tail_check([], St) -> St.
+
%% pat_bit_expr(SizePat, Type, Defined, State) -> State.
%% Check the Size pattern, this is an input! Because of optimizations,
%% we must allow any kind of constant and literal here.
diff --git a/lib/compiler/src/v3_codegen.erl b/lib/compiler/src/v3_codegen.erl
index 948937c438..77da6c8d00 100644
--- a/lib/compiler/src/v3_codegen.erl
+++ b/lib/compiler/src/v3_codegen.erl
@@ -1523,7 +1523,9 @@ cg_binary_size_1([], Bits, Acc) ->
[{1,_}|_] ->
{bs_init_bits,cg_binary_bytes_to_bits(Sizes, [])};
[{8,_}|_] ->
- {bs_init2,[E || {8,E} <- Sizes]}
+ {bs_init2,[E || {8,E} <- Sizes]};
+ [] ->
+ {bs_init_bits,[]}
end.
cg_binary_size_2({integer,N}, U, _, Next, Bits, Acc) ->
diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl
index f6bb45787c..2da24b2908 100644
--- a/lib/compiler/src/v3_core.erl
+++ b/lib/compiler/src/v3_core.erl
@@ -892,25 +892,22 @@ lc_tq(Line, E, [{generate,Lg,P,G}|Qs0], Mc, St0) ->
lc_tq(Line, E, [{b_generate,Lg,P,G}|Qs0], Mc, St0) ->
{Gs,Qs1} = splitwith(fun is_guard_test/1, Qs0),
{Name,St1} = new_fun_name("blc", St0),
- {Tname,St2} = new_var_name(St1),
- LA = lineno_anno(Line, St2),
+ LA = lineno_anno(Line, St1),
LAnno = #a{anno=LA},
- HeadBinPattern = pattern(P,St2),
- #c_binary{segments=Ps} = HeadBinPattern,
- {EPs,St3} = emasculate_segments(Ps,St2),
- Tail = #c_var{anno=LA,name=Tname},
- TailSegment = #c_bitstr{val=Tail,size=#c_literal{val=all},
- unit=#c_literal{val=1},
- type=#c_literal{val=binary},
- flags=#c_literal{val=[big,unsigned]}},
- Pattern = HeadBinPattern#c_binary{segments=Ps ++ [TailSegment]},
- EPattern = HeadBinPattern#c_binary{segments=EPs ++ [TailSegment]},
+ HeadBinPattern = pattern(P, St1),
+ #c_binary{segments=Ps0} = HeadBinPattern,
+ {Ps,Tail,St2} = append_tail_segment(Ps0, St1),
+ {EPs,St3} = emasculate_segments(Ps, St2),
+ Pattern = HeadBinPattern#c_binary{segments=Ps},
+ EPattern = HeadBinPattern#c_binary{segments=EPs},
{Arg,St4} = new_var(St3),
{Guardc,St5} = lc_guard_tests(Gs, St4), %These are always flat!
+ Tname = Tail#c_var.name,
{Nc,[],St6} = expr({call,Lg,{atom,Lg,Name},[{var,Lg,Tname}]}, St5),
{Bc,Bps,St7} = lc_tq(Line, E, Qs1, Nc, St6),
{Gc,Gps,St10} = safe(G, St7), %Will be a function argument!
Fc = function_clause([Arg], LA, {Name,1}),
+ {TailSegList,_,St} = append_tail_segment([], St10),
Cs = [#iclause{anno=#a{anno=[compiler_generated|LA]},
pats=[Pattern],
guard=Guardc,
@@ -922,14 +919,14 @@ lc_tq(Line, E, [{b_generate,Lg,P,G}|Qs0], Mc, St0) ->
op=#c_var{anno=LA,name={Name,1}},
args=[Tail]}]},
#iclause{anno=LAnno,
- pats=[#c_binary{anno=LA, segments=[TailSegment]}],guard=[],
+ pats=[#c_binary{anno=LA,segments=TailSegList}],guard=[],
body=[Mc]}],
Fun = #ifun{anno=LAnno,id=[],vars=[Arg],clauses=Cs,fc=Fc},
{#iletrec{anno=LAnno,defs=[{{Name,1},Fun}],
body=Gps ++ [#iapply{anno=LAnno,
op=#c_var{anno=LA,name={Name,1}},
args=[Gc]}]},
- [],St10};
+ [],St};
lc_tq(Line, E, [Fil0|Qs0], Mc, St0) ->
%% Special case sequences guard tests.
LA = lineno_anno(Line, St0),
@@ -1037,26 +1034,24 @@ bc_tq1(Line, E, [{b_generate,Lg,P,G}|Qs0], AccExpr, St0) ->
{Gs,Qs1} = splitwith(fun is_guard_test/1, Qs0),
{Name,St1} = new_fun_name("lbc", St0),
LA = lineno_anno(Line, St1),
- {[Tail,AccVar],St2} = new_vars(LA, 2, St1),
+ {AccVar,St2} = new_var(LA, St1),
LAnno = #a{anno=LA},
HeadBinPattern = pattern(P, St2),
- #c_binary{segments=Ps} = HeadBinPattern,
- {EPs,St3} = emasculate_segments(Ps, St2),
- TailSegment = #c_bitstr{val=Tail,size=#c_literal{val=all},
- unit=#c_literal{val=1},
- type=#c_literal{val=binary},
- flags=#c_literal{val=[big,unsigned]}},
- Pattern = HeadBinPattern#c_binary{segments=Ps ++ [TailSegment]},
- EPattern = HeadBinPattern#c_binary{segments=EPs ++ [TailSegment]},
- {Arg,St4} = new_var(St3),
+ #c_binary{segments=Ps0} = HeadBinPattern,
+ {Ps,Tail,St3} = append_tail_segment(Ps0, St2),
+ {EPs,St4} = emasculate_segments(Ps, St3),
+ Pattern = HeadBinPattern#c_binary{segments=Ps},
+ EPattern = HeadBinPattern#c_binary{segments=EPs},
+ {Arg,St5} = new_var(St4),
NewMore = {call,Lg,{atom,Lg,Name},[{var,Lg,Tail#c_var.name},
{var,Lg,AccVar#c_var.name}]},
- {Guardc,St5} = lc_guard_tests(Gs, St4), %These are always flat!
- {Bc,Bps,St6} = bc_tq1(Line, E, Qs1, AccVar, St5),
- {Nc,Nps,St7} = expr(NewMore, St6),
- {Gc,Gps,St8} = safe(G, St7), %Will be a function argument!
+ {Guardc,St6} = lc_guard_tests(Gs, St5), %These are always flat!
+ {Bc,Bps,St7} = bc_tq1(Line, E, Qs1, AccVar, St6),
+ {Nc,Nps,St8} = expr(NewMore, St7),
+ {Gc,Gps,St9} = safe(G, St8), %Will be a function argument!
Fc = function_clause([Arg,AccVar], LA, {Name,2}),
Body = Bps ++ Nps ++ [#iset{var=AccVar,arg=Bc},Nc],
+ {TailSegList,_,St} = append_tail_segment([], St9),
Cs = [#iclause{anno=LAnno,
pats=[Pattern,AccVar],
guard=Guardc,
@@ -1066,7 +1061,7 @@ bc_tq1(Line, E, [{b_generate,Lg,P,G}|Qs0], AccExpr, St0) ->
guard=[],
body=Nps ++ [Nc]},
#iclause{anno=LAnno,
- pats=[#c_binary{anno=LA,segments=[TailSegment]},AccVar],
+ pats=[#c_binary{anno=LA,segments=TailSegList},AccVar],
guard=[],
body=[AccVar]}],
Fun = #ifun{anno=LAnno,id=[],vars=[Arg,AccVar],clauses=Cs,fc=Fc},
@@ -1074,7 +1069,7 @@ bc_tq1(Line, E, [{b_generate,Lg,P,G}|Qs0], AccExpr, St0) ->
body=Gps ++ [#iapply{anno=LAnno,
op=#c_var{anno=LA,name={Name,2}},
args=[Gc,AccExpr]}]},
- [],St8};
+ [],St};
bc_tq1(Line, E, [Fil0|Qs0], AccVar, St0) ->
%% Special case sequences guard tests.
LA = lineno_anno(Line, St0),
@@ -1120,6 +1115,29 @@ bc_tq1(_, {bin,Bl,Elements}, [], AccVar, St0) ->
%%Anno = Anno0#a{anno=[compiler_generated|A]},
{set_anno(E, Anno),Pre,St}.
+append_tail_segment(Segs, St) ->
+ app_tail_seg(Segs, St, []).
+
+app_tail_seg([#c_bitstr{val=Var0,size=#c_literal{val=all}}=Seg0]=L,
+ St0, Acc) ->
+ case Var0 of
+ #c_var{name='_'} ->
+ {Var,St} = new_var(St0),
+ Seg = Seg0#c_bitstr{val=Var},
+ {reverse(Acc, [Seg]),Var,St};
+ #c_var{} ->
+ {reverse(Acc, L),Var0,St0}
+ end;
+app_tail_seg([H|T], St, Acc) ->
+ app_tail_seg(T, St, [H|Acc]);
+app_tail_seg([], St0, Acc) ->
+ {Var,St} = new_var(St0),
+ Tail = #c_bitstr{val=Var,size=#c_literal{val=all},
+ unit=#c_literal{val=1},
+ type=#c_literal{val=binary},
+ flags=#c_literal{val=[unsigned,big]}},
+ {reverse(Acc, [Tail]),Var,St}.
+
emasculate_segments(Segs, St) ->
emasculate_segments(Segs, St, []).
diff --git a/lib/compiler/test/bs_bincomp_SUITE.erl b/lib/compiler/test/bs_bincomp_SUITE.erl
index a64a5d590b..74f69893af 100644
--- a/lib/compiler/test/bs_bincomp_SUITE.erl
+++ b/lib/compiler/test/bs_bincomp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -24,7 +24,7 @@
-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]).
+ nomatch/1,sizes/1,tail/1]).
-include("test_server.hrl").
@@ -32,7 +32,7 @@ all(suite) ->
test_lib:recompile(?MODULE),
[byte_aligned,bit_aligned,extended_byte_aligned,
extended_bit_aligned,mixed,filters,trim_coverage,
- nomatch,sizes].
+ nomatch,sizes,tail].
byte_aligned(Config) when is_list(Config) ->
@@ -270,6 +270,38 @@ sizes(Config) when is_list(Config) ->
?line cs_end(),
ok.
+tail(Config) when is_list(Config) ->
+ ?line [] = tail_1(<<0:7>>),
+ ?line [0] = tail_1(<<0>>),
+ ?line [0] = tail_1(<<0:12>>),
+ ?line [0,0] = tail_1(<<0:20>>),
+
+ ?line [] = tail_2(<<0:7>>),
+ ?line [42] = tail_2(<<0>>),
+ ?line [] = tail_2(<<0:12>>),
+ ?line [42,42] = tail_2(<<0,1>>),
+
+ ?line <<>> = tail_3(<<0:7>>),
+ ?line <<42>> = tail_3(<<0>>),
+ ?line <<42>> = tail_3(<<0:12>>),
+ ?line <<42,42>> = tail_3(<<0:20>>),
+
+ ?line [] = tail_4(<<0:15>>),
+ ?line [7] = tail_4(<<7,8>>),
+ ?line [9] = tail_4(<<9,17:12>>),
+ ok.
+
+tail_1(Bits) ->
+ [X || <<X:8/integer, _/bits>> <= Bits].
+
+tail_2(Bits) ->
+ [42 || <<_:8/integer, _/bytes>> <= Bits].
+
+tail_3(Bits) ->
+ << <<42>> || <<_:8/integer, _/bits>> <= Bits >>.
+
+tail_4(Bits) ->
+ [X || <<X:8/integer, Tail/bits>> <= Bits, bit_size(Tail) >= 8].
cs_init() ->
diff --git a/lib/compiler/test/bs_construct_SUITE.erl b/lib/compiler/test/bs_construct_SUITE.erl
index 1862a28bbe..dfe4301791 100644
--- a/lib/compiler/test/bs_construct_SUITE.erl
+++ b/lib/compiler/test/bs_construct_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -66,6 +66,8 @@ id(I) -> I.
l(I_13, I_big1, I_16, Bin) ->
[
+ ?T(<<I_13:0>>,
+ []),
?T(<<-43>>,
[256-43]),
?T(<<4:4,7:4>>,
diff --git a/lib/compiler/test/receive_SUITE.erl b/lib/compiler/test/receive_SUITE.erl
index fca3f0387b..2a592dd669 100644
--- a/lib/compiler/test/receive_SUITE.erl
+++ b/lib/compiler/test/receive_SUITE.erl
@@ -21,7 +21,7 @@
-module(receive_SUITE).
-export([all/1,init_per_testcase/2,fin_per_testcase/2,
- recv/1,coverage/1,otp_7980/1,ref_opt/1]).
+ recv/1,coverage/1,otp_7980/1,ref_opt/1,export/1]).
-include("test_server.hrl").
@@ -36,7 +36,7 @@ fin_per_testcase(_Case, Config) ->
all(suite) ->
test_lib:recompile(?MODULE),
- [recv,coverage,otp_7980,ref_opt].
+ [recv,coverage,otp_7980,ref_opt,export].
-record(state, {ena = true}).
@@ -205,4 +205,25 @@ collect_recv_opt_instrs(Code) ->
end] || {function,_,_,_,Is} <- Code],
lists:append(L).
+export(Config) when is_list(Config) ->
+ Ref = make_ref(),
+ ?line self() ! {result,Ref,42},
+ ?line 42 = export_1(Ref),
+ ?line {error,timeout} = export_1(Ref),
+ ok.
+
+export_1(Reference) ->
+ id(Reference),
+ receive
+ {result,Reference,Result} ->
+ Result
+ after 1 ->
+ Result = {error,timeout}
+ end,
+ %% Result ({x,1}) is used, but not the return value ({x,0})
+ %% of the receive. Used to be incorrectly optimized
+ %% by beam_block.
+ id({build,self()}),
+ Result.
+
id(I) -> I.
diff --git a/lib/compiler/vsn.mk b/lib/compiler/vsn.mk
index 47feab5fe1..4658eccd19 100644
--- a/lib/compiler/vsn.mk
+++ b/lib/compiler/vsn.mk
@@ -1 +1 @@
-COMPILER_VSN = 4.7
+COMPILER_VSN = 4.7.1
diff --git a/lib/cosEvent/vsn.mk b/lib/cosEvent/vsn.mk
index 9f326b39b6..9c00a17100 100644
--- a/lib/cosEvent/vsn.mk
+++ b/lib/cosEvent/vsn.mk
@@ -1,15 +1 @@
-
COSEVENT_VSN = 2.1.9
-
-TICKETS = OTP-8543
-
-TICKETS_2.1.8 = OTP-8355 \
- OTP-8409
-
-TICKETS_2.1.7 = OTP-8201
-
-TICKETS_2.1.6 = OTP-7987
-
-TICKETS_2.1.5 = OTP-7837
-
-TICKETS_2.1.4 = OTP-7595
diff --git a/lib/cosEventDomain/vsn.mk b/lib/cosEventDomain/vsn.mk
index dceee34181..bd21133fe5 100644
--- a/lib/cosEventDomain/vsn.mk
+++ b/lib/cosEventDomain/vsn.mk
@@ -1,15 +1 @@
-
COSEVENTDOMAIN_VSN = 1.1.9
-
-TICKETS = OTP-8543
-
-TICKETS_1.1.8 = OTP-8353 \
- OTP-8355
-
-TICKETS_1.1.7 = OTP-8201
-
-TICKETS_1.1.6 = OTP-7987
-
-TICKETS_1.1.5 = OTP-7837
-
-TICKETS_1.1.4 = OTP-7595
diff --git a/lib/cosFileTransfer/test/Makefile b/lib/cosFileTransfer/test/Makefile
new file mode 100644
index 0000000000..60f72644bd
--- /dev/null
+++ b/lib/cosFileTransfer/test/Makefile
@@ -0,0 +1,132 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2000-2010. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+#
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../vsn.mk
+VSN=$(COSFILETRANSFER_VSN)
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/cosFileTransfer_test
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+TEST_SPEC_FILE = cosFileTransfer.spec
+
+
+IDL_FILES =
+
+IDLOUTDIR = idl_output
+
+MODULES = \
+ fileTransfer_SUITE \
+
+GEN_MODULES = \
+
+GEN_HRL_FILES = \
+
+ERL_FILES = $(MODULES:%=%.erl)
+
+HRL_FILES =
+
+GEN_FILES = \
+ $(GEN_HRL_FILES:%=$(IDLOUTDIR)/%) \
+ $(GEN_MODULES:%=$(IDLOUTDIR)/%.erl)
+
+GEN_TARGET_FILES = $(GEN_MODULES:%=$(IDLOUTDIR)/%.$(EMULATOR))
+
+SUITE_TARGET_FILES = $(MODULES:%=%.$(EMULATOR))
+
+TARGET_FILES = \
+ $(GEN_TARGET_FILES) \
+ $(SUITE_TARGET_FILES)
+
+
+# ----------------------------------------------------
+# PROGRAMS
+# ----------------------------------------------------
+LOCAL_CLASSPATH = $(ERL_TOP)lib/cosFileTransfer/priv:$(ERL_TOP)lib/cosFileTransfer/test
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+ERL_IDL_FLAGS += -pa $(ERL_TOP)/lib/cosFileTransfer/ebin \
+ -pa $(ERL_TOP)/lib/cosFileTransfer/src \
+ -pa $(ERL_TOP)/lib/cosFileTransfer/include \
+ -pa $(ERL_TOP)/lib/cosProperty/ebin \
+ -pa $(ERL_TOP)/lib/cosProperty/include \
+ -pa $(ERL_TOP)/lib/orber/ebin \
+ -pa $(ERL_TOP)/lib/ic/ebin
+
+ERL_COMPILE_FLAGS += \
+ $(ERL_IDL_FLAGS) \
+ -pa $(ERL_TOP)/lib/orber/include \
+ -pa $(ERL_TOP)/lib/cosProperty/include \
+ -pa $(ERL_TOP)/internal_tools/test_server/ebin \
+ -pa $(ERL_TOP)/lib/cosFileTransfer/ebin \
+ -pa $(ERL_TOP)/lib/cosFileTransfer/include \
+ -pa $(ERL_TOP)/lib/cosFileTransfer/test/idl_output \
+ -I$(ERL_TOP)/lib/orber/include \
+ -I$(ERL_TOP)/lib/cosProperty/include \
+ -I$(ERL_TOP)/lib/cosFileTransfer/src \
+ -I$(ERL_TOP)/lib/cosFileTransfer/include \
+ -I$(ERL_TOP)/lib/cosFileTransfer \
+ -I$(ERL_TOP)/lib/cosFileTransfer/test/$(IDLOUTDIR) \
+ -I$(ERL_TOP)/lib/test_server/include
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+
+tests debug opt: $(TARGET_FILES)
+
+clean:
+ rm -f idl_output/*
+ rm -f $(TARGET_FILES)
+ rm -f errs core *~
+
+docs:
+
+# ----------------------------------------------------
+# Special Targets
+# ----------------------------------------------------
+
+# ----------------------------------------------------
+# Release Targets
+# ----------------------------------------------------
+# We don't copy generated intermediate erlang and hrl files
+
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_spec:
+
+release_docs_spec:
+
+release_tests_spec: tests
+ $(INSTALL_DIR) $(RELSYSDIR)
+ $(INSTALL_DATA) $(IDL_FILES) $(TEST_SPEC_FILE) \
+ $(ERL_FILES) $(RELSYSDIR)
+ $(INSTALL_DATA) $(SUITE_TARGET_FILES) $(RELSYSDIR)
+ chmod -f -R u+w $(RELSYSDIR)
diff --git a/lib/cosFileTransfer/test/cosFileTransfer.spec b/lib/cosFileTransfer/test/cosFileTransfer.spec
new file mode 100644
index 0000000000..80fe919f2a
--- /dev/null
+++ b/lib/cosFileTransfer/test/cosFileTransfer.spec
@@ -0,0 +1 @@
+{topcase, {dir, "../cosFileTransfer_test"}}.
diff --git a/lib/cosFileTransfer/test/fileTransfer_SUITE.erl b/lib/cosFileTransfer/test/fileTransfer_SUITE.erl
new file mode 100644
index 0000000000..f877e3ceda
--- /dev/null
+++ b/lib/cosFileTransfer/test/fileTransfer_SUITE.erl
@@ -0,0 +1,954 @@
+%%-----------------------------------------------------------------------
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2000-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+%%----------------------------------------------------------------------
+%% File : fileTransfer_SUITE.erl
+%% Purpose :
+%%----------------------------------------------------------------------
+
+-module(fileTransfer_SUITE).
+
+
+
+%%--------------- INCLUDES -----------------------------------
+-include_lib("cosFileTransfer/src/cosFileTransferApp.hrl").
+
+-include("test_server.hrl").
+
+%%--------------- DEFINES ------------------------------------
+-define(default_timeout, ?t:minutes(20)).
+-define(match(ExpectedRes, Expr),
+ fun() ->
+ AcTuAlReS = (catch (Expr)),
+ case AcTuAlReS of
+ ExpectedRes ->
+ io:format("------ CORRECT RESULT ------~n~p~n",
+ [AcTuAlReS]),
+ AcTuAlReS;
+ _ ->
+ io:format("###### ERROR ERROR ######~n~p~n",
+ [AcTuAlReS]),
+ exit(AcTuAlReS)
+ end
+ end()).
+
+-define(matchnopr(ExpectedRes, Expr),
+ fun() ->
+ AcTuAlReS = (catch (Expr)),
+ case AcTuAlReS of
+ ExpectedRes ->
+ io:format("------ CORRECT RESULT (~p) ------~n", [?LINE]),
+ AcTuAlReS;
+ _ ->
+ io:format("###### ERROR ERROR ######~n~p~n",
+ [AcTuAlReS]),
+ exit(AcTuAlReS)
+ end
+ end()).
+
+
+
+
+
+%%-----------------------------------------------------------------
+%% External exports
+%%-----------------------------------------------------------------
+-export([all/1,
+ cases/0,
+ init_all/1,
+ finish_all/1,
+ fileIterator_api/1,
+ fts_ftp_file_api/1,
+ fts_ftp_file_ssl_api/1,
+ fts_ftp_dir_api/1,
+ fts_native_file_api/1,
+ fts_native_file_ssl_api/1,
+ fts_native_dir_api/1,
+ init_per_testcase/2,
+ fin_per_testcase/2,
+ install_data/2,
+ uninstall_data/1,
+ slave_sup/0,
+ app_test/1]).
+
+%%-----------------------------------------------------------------
+%% Func: all/1
+%% Args:
+%% Returns:
+%%-----------------------------------------------------------------
+all(doc) -> ["API tests for the cosFileTransfer interfaces", ""];
+all(suite) -> {req,
+ [mnesia, orber],
+ {conf, init_all, cases(), finish_all}}.
+
+cases() ->
+ [fts_ftp_dir_api, fts_ftp_file_api, fts_ftp_file_ssl_api,
+ fts_native_dir_api, fts_native_file_api, fts_native_file_ssl_api,
+ fileIterator_api, app_test].
+
+%%-----------------------------------------------------------------
+%% Init and cleanup functions.
+%%-----------------------------------------------------------------
+
+init_per_testcase(_Case, Config) ->
+ ?line Dog=test_server:timetrap(?default_timeout),
+ [{watchdog, Dog}|Config].
+
+
+fin_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ test_server:timetrap_cancel(Dog),
+ ok.
+
+init_all(Config) ->
+ orber:jump_start(),
+ cosProperty:install(),
+ cosProperty:start(),
+ Dir = filename:join([code:lib_dir(ssl), "examples", "certs", "etc"]),
+ %% Client
+ cosFileTransferApp:configure(ssl_client_certfile,
+ filename:join([Dir, "client", "cert.pem"])),
+ cosFileTransferApp:configure(ssl_client_cacertfile,
+ filename:join([Dir, "client", "cacerts.pem"])),
+ cosFileTransferApp:configure(ssl_client_verify, 1),
+ cosFileTransferApp:configure(ssl_client_depth, 0),
+ %% Server
+ cosFileTransferApp:configure(ssl_server_certfile,
+ filename:join([Dir, "server", "cert.pem"])),
+ cosFileTransferApp:configure(ssl_server_cacertfile,
+ filename:join([Dir, "server", "cacerts.pem"])),
+ cosFileTransferApp:configure(ssl_server_verify, 1),
+ cosFileTransferApp:configure(ssl_server_depth, 0),
+ crypto:start(),
+ ssl:start(),
+ cosFileTransferApp:install(),
+ cosFileTransferApp:start(),
+ if
+ is_list(Config) ->
+ Config;
+ true ->
+ exit("Config not a list")
+ end.
+
+finish_all(Config) ->
+ ssl:stop(),
+ crypto:stop(),
+ cosFileTransferApp:stop(),
+ cosProperty:stop(),
+ cosProperty:uninstall(),
+ cosFileTransferApp:uninstall(),
+ orber:jump_stop(),
+ Config.
+
+%%-----------------------------------------------------------------
+%% Local definitions
+%%-----------------------------------------------------------------
+-define(FTP_USER, "anonymous").
+-define(FTP_PASS, "fileTransfer_SUITE@localhost").
+-define(TEST_DIR,["/", "incoming"]).
+
+
+-define(FTP_PORT, 21).
+-define(FTP_ACC, "anonymous").
+
+-define(BAD_HOST, "badhostname").
+-define(BAD_USER, "baduser").
+-define(BAD_DIR, "baddirectory").
+
+-define(TEST_FILE_DATA, "If this file exists after a completed test an error occurred.").
+-define(TEST_FILE_DATA2, "1234567890123").
+
+
+%%-----------------------------------------------------------------
+%% aoo-file test
+%%-----------------------------------------------------------------
+app_test(doc) -> [];
+app_test(suite) -> [];
+app_test(_Config) ->
+ ?line ok=?t:app_test(cosFileTransfer),
+ ok.
+
+%%-----------------------------------------------------------------
+%% FileIterator API tests
+%%-----------------------------------------------------------------
+fileIterator_api(doc) -> ["CosFileTransfer FileIterator API tests.", ""];
+fileIterator_api(suite) -> [];
+fileIterator_api(Config) ->
+ case ftp_host(Config) of
+ {skipped, SkippedReason} ->
+ {skipped, SkippedReason};
+ Host ->
+
+ ?line {ok, Node} = create_node("fileIterator_api", 4008, normal),
+ ?line ?match(ok, remote_apply(Node, ?MODULE, install_data,
+ [tcp, {{'NATIVE',
+ 'cosFileTransferNATIVE_file'}, Host,
+ "fileIterator_api"}])),
+
+ %% Create a Virtual File System.
+%% ?line VFS = ?match({_,_,_,_,_,_},
+%% cosFileTransferApp:create_VFS({'NATIVE',
+%% 'cosFileTransferNATIVE_file'},
+%% [], Host, ?FTP_PORT)),
+ ?line VFS = ?matchnopr({'IOP_IOR',"IDL:omg.org/CosFileTransfer/VirtualFileSystem:1.0",_},
+ corba:string_to_object("corbaname::1.2@localhost:4008/NameService#fileIterator_api")),
+
+ %% Start two File Transfer Sessions (Source and Target).
+ ?line {FS, Dir} = ?matchnopr({{_,_,_},{_,_,_}},
+ 'CosFileTransfer_VirtualFileSystem':login(VFS,
+ ?FTP_USER,
+ ?FTP_PASS,
+ ?FTP_ACC)),
+
+ %% Do some basic test on one of the Directories attributes.
+ ?line ?match([_H|_], 'CosFileTransfer_Directory':'_get_name'(Dir)),
+ ?line ?match([_H|_], 'CosFileTransfer_Directory':'_get_complete_file_name'(Dir)),
+ ?line ?match({'IOP_IOR',[],[]}, 'CosFileTransfer_Directory':'_get_parent'(Dir)),
+ ?line ?matchnopr(FS, 'CosFileTransfer_Directory':'_get_associated_session'(Dir)),
+ {ok,[],FileIter} = ?match({ok,[],_}, 'CosFileTransfer_Directory':list(Dir, 0)),
+ %% Usually the working directory for the test is not empty so no need for
+ %% creating files of our own?!
+ #any{value=Children} = ?match({any, _, _},
+ 'CosPropertyService_PropertySet':
+ get_property_value(Dir, "num_children")),
+
+ if
+ Children > 5 ->
+ ?line ?matchnopr({true, _}, 'CosFileTransfer_FileIterator':next_one(FileIter)),
+ ?line ?matchnopr({true, _}, 'CosFileTransfer_FileIterator':next_n(FileIter, 3)),
+ ?line ?matchnopr({true, _}, 'CosFileTransfer_FileIterator':next_n(FileIter,
+ Children)),
+ ?line ?matchnopr({false, _}, 'CosFileTransfer_FileIterator':next_one(FileIter)),
+ ?line ?match({false, []}, 'CosFileTransfer_FileIterator':next_n(FileIter, 1)),
+ ok;
+ true ->
+ ok
+ end,
+ ?line ?match(ok, 'CosFileTransfer_FileIterator':destroy(FileIter)),
+ ?line ?match(false, corba_object:non_existent(FS)),
+ ?line ?match(ok, 'CosFileTransfer_FileTransferSession':logout(FS)),
+ %% To make sure Orber can remove it from mnesia.
+ timer:sleep(1000),
+ ?line ?match(true, corba_object:non_existent(FS)),
+ ?line ?match(ok, remote_apply(Node, ?MODULE, uninstall_data, ["fileIterator_api"])),
+ stop_orber_remote(Node, normal),
+ ok
+ end.
+
+
+%%-----------------------------------------------------------------
+%% FileTransferSession API tests
+%%-----------------------------------------------------------------
+fts_ftp_file_api(doc) -> ["CosFileTransfer FTP FileTransferSession API tests.", ""];
+fts_ftp_file_api(suite) -> [];
+fts_ftp_file_api(Config) ->
+ ?line {ok, Node} = create_node("ftp_file_api", 4004, normal),
+ file_helper(Config, 'FTP', ?TEST_DIR, Node, 4004, "ftp_file_api", tcp).
+
+fts_ftp_file_ssl_api(doc) -> ["CosFileTransfer FTP FileTransferSession API tests.", ""];
+fts_ftp_file_ssl_api(suite) -> [];
+fts_ftp_file_ssl_api(Config) ->
+ case os:type() of
+ vxworks ->
+ {skipped, "No SSL-support for VxWorks."};
+ _ ->
+ ?line {ok, Node} = create_node("ftp_file_api_ssl", {4005, 1}, ssl),
+ file_helper(Config, 'FTP', ?TEST_DIR, Node, 4005, "ftp_file_api_ssl", ssl)
+ end.
+
+fts_native_file_api(doc) -> ["CosFileTransfer NATIVE FileTransferSession API tests.", ""];
+fts_native_file_api(suite) -> [];
+fts_native_file_api(Config) ->
+ ?line {ok, Node} = create_node("native_file_api", 4006, normal),
+ {ok, Pwd} = file:get_cwd(),
+ file_helper(Config,{'NATIVE', 'cosFileTransferNATIVE_file'},filename:split(Pwd),
+ Node, 4006, "native_file_api", tcp).
+
+fts_native_file_ssl_api(doc) -> ["CosFileTransfer NATIVE FileTransferSession API tests.", ""];
+fts_native_file_ssl_api(suite) -> [];
+fts_native_file_ssl_api(Config) ->
+ case os:type() of
+ vxworks ->
+ {skipped, "No SSL-support for VxWorks."};
+ _ ->
+ ?line {ok, Node} = create_node("native_file_ssl_api", {4007, 1}, ssl),
+ {ok, Pwd} = file:get_cwd(),
+ file_helper(Config,{'NATIVE', 'cosFileTransferNATIVE_file'},filename:split(Pwd),
+ Node, 4007, "native_file_ssl_api", ssl)
+ end.
+
+
+
+file_helper(Config, WhichType, TEST_DIR, Node, Port, Name, Type) ->
+ case ftp_host(Config) of
+ {skipped, SkippedReason} ->
+ {skipped, SkippedReason};
+ Host ->
+ TEST_SOURCE = TEST_DIR ++ [create_name(remove_me_source)],
+ TEST_SOURCE2 = TEST_DIR ++ [create_name(remove_me_source)],
+ TEST_TARGET = TEST_DIR ++ [create_name(remove_me_target)],
+
+ io:format("<<<<<< CosFileTransfer Testing Configuration >>>>>>~n",[]),
+ io:format("Source: ~p~nTarget: ~p~n", [TEST_SOURCE, TEST_TARGET]),
+
+ ?line ?match(ok, remote_apply(Node, ?MODULE, install_data,
+ [Type, {WhichType, Host, Name}])),
+
+ ?line VFST = ?match({'IOP_IOR',"IDL:omg.org/CosFileTransfer/VirtualFileSystem:1.0",_},
+ corba:string_to_object("corbaname::1.2@localhost:"++integer_to_list(Port)++"/NameService#"++Name)),
+
+
+ %% Create a Virtual File System.
+ ?line VFS = ?match({_,_,_,_,_,_},
+ cosFileTransferApp:create_VFS(WhichType, [], Host, ?FTP_PORT,
+ [{protocol, Type}])),
+ %% Start two File Transfer Sessions (Source and Target).
+ ?line {FST, _DirT} = ?match({{_,_,_},{_,_,_}},
+ 'CosFileTransfer_VirtualFileSystem':login(VFST,
+ ?FTP_USER,
+ ?FTP_PASS,
+ ?FTP_ACC)),
+ ?line {FSS, DirS} = ?match({{_,_,_,_,_,_},{_,_,_,_,_,_}},
+ 'CosFileTransfer_VirtualFileSystem':login(VFS,
+ ?FTP_USER,
+ ?FTP_PASS,
+ ?FTP_ACC)),
+
+ %% Do some basic test on one of the Directories attributes.
+ ?line ?match([_H|_], 'CosFileTransfer_Directory':'_get_name'(DirS)),
+ ?line ?match([_H|_], 'CosFileTransfer_Directory':'_get_complete_file_name'(DirS)),
+ ?line ?match({'IOP_IOR',[],[]}, 'CosFileTransfer_Directory':'_get_parent'(DirS)),
+ ?line ?match(FSS, 'CosFileTransfer_Directory':'_get_associated_session'(DirS)),
+
+ %% Get a FileList before we create any new Files
+ ?line #'CosFileTransfer_FileWrapper'{the_file = Dir} =
+ ?match({'CosFileTransfer_FileWrapper', _, ndirectory},
+ 'CosFileTransfer_FileTransferSession':get_file(FSS, TEST_DIR)),
+ ?line {ok,FileList, Iter1} = ?match({ok,_,_}, 'CosFileTransfer_Directory':list(Dir, 10)),
+ ?line loop_files(FileList),
+
+ case Iter1 of
+ {'IOP_IOR',[],[]} ->
+ ok;
+ _->
+ ?line ?match(ok, 'CosFileTransfer_FileIterator':destroy(Iter1))
+ end,
+
+ #any{value=Count1} = ?match({any, _, _}, 'CosPropertyService_PropertySet':
+ get_property_value(Dir, "num_children")),
+
+ %% Now we want to transfer a file from source to target. First, we'll create
+ %% a a file to work with.
+ ?line create_file_on_source_node(WhichType, Config, Host,
+ filename:join(TEST_SOURCE), TEST_DIR,
+ ?TEST_FILE_DATA),
+ ?line create_file_on_source_node(WhichType, Config, Host,
+ filename:join(TEST_SOURCE2), TEST_DIR,
+ ?TEST_FILE_DATA2),
+
+ ?line #'CosFileTransfer_FileWrapper'{the_file = FileS} =
+ ?matchnopr({'CosFileTransfer_FileWrapper', _, nfile},
+ 'CosFileTransfer_FileTransferSession':get_file(FSS, TEST_SOURCE)),
+ ?line #'CosFileTransfer_FileWrapper'{the_file = FileS2} =
+ ?matchnopr({'CosFileTransfer_FileWrapper', _, nfile},
+ 'CosFileTransfer_FileTransferSession':get_file(FSS, TEST_SOURCE2)),
+
+ #any{value=Count2} = ?match({any, _, _}, 'CosPropertyService_PropertySet':
+ get_property_value(Dir, "num_children")),
+ timer:sleep(2000),
+ ?match(true, (Count1+2 == Count2)),
+
+ %% Create a target File
+ ?line FileT = ?matchnopr({_,_,_},
+ 'CosFileTransfer_FileTransferSession':create_file(FST, TEST_TARGET)),
+ %% Try to delete the non-existing file.
+ ?line ?match({'EXCEPTION', _},
+ 'CosFileTransfer_FileTransferSession':delete(FST, FileT)),
+
+ ?line ?match(ok, 'CosFileTransfer_FileTransferSession':transfer(FSS, FileS, FileT)),
+
+ %% Remove this test when ftp supports append.
+ case WhichType of
+ {'NATIVE', 'cosFileTransferNATIVE_file'} ->
+ ?line ?match(ok, 'CosFileTransfer_FileTransferSession':append(FSS, FileS, FileT)),
+ ?line ?match(ok, 'CosFileTransfer_FileTransferSession':insert(FSS, FileS2, FileT, 7));
+ _->
+ ok
+ end,
+
+ %% Delete source and target files
+ ?line ?match(ok, 'CosFileTransfer_FileTransferSession':delete(FSS, FileS)),
+ ?line ?match(ok, 'CosFileTransfer_FileTransferSession':delete(FSS, FileS2)),
+ ?line ?match(ok, 'CosFileTransfer_FileTransferSession':delete(FST, FileT)),
+
+ %% Should be back where we started.
+ timer:sleep(2000),
+ #any{value=Count3} = ?match({any, _, _}, 'CosPropertyService_PropertySet':
+ get_property_value(Dir, "num_children")),
+ ?match(true, (Count1 == Count3)),
+
+
+ ?line ?match(false, corba_object:non_existent(FSS)),
+ ?line ?match(false, corba_object:non_existent(FST)),
+ ?line ?match(ok, 'CosFileTransfer_FileTransferSession':logout(FSS)),
+ ?line ?match(ok, 'CosFileTransfer_FileTransferSession':logout(FST)),
+ %% To make sure Orber can remove it from mnesia.
+ timer:sleep(2000),
+ ?line ?match(true, corba_object:non_existent(FSS)),
+ ?line ?match(true, corba_object:non_existent(FST)),
+ ?line ?match(ok, remote_apply(Node, ?MODULE, uninstall_data, [Name])),
+ stop_orber_remote(Node, normal),
+ ok
+ end.
+
+%%-----------------------------------------------------------------
+%% FileTransferSession API tests
+%%-----------------------------------------------------------------
+fts_ftp_dir_api(doc) -> ["CosFileTransfer FTP FileTransferSession API tests.", ""];
+fts_ftp_dir_api(suite) -> [];
+fts_ftp_dir_api(Config) ->
+ ?line {ok, Node} = create_node("ftp_dir_api", 4009, normal),
+ dir_helper(Config, 'FTP', ?TEST_DIR, Node, 4009, "ftp_dir_api").
+
+
+fts_native_dir_api(doc) -> ["CosFileTransfer NATIVE FileTransferSession API tests.", ""];
+fts_native_dir_api(suite) -> [];
+fts_native_dir_api(Config) ->
+ ?line {ok, Node} = create_node("native_dir_api", 4010, normal),
+ {ok, Pwd} = file:get_cwd(),
+ dir_helper(Config, {'NATIVE', 'cosFileTransferNATIVE_file'},
+ filename:split(Pwd), Node, 4010, "native_dir_api").
+
+dir_helper(Config, WhichType, TEST_DIR, Node, Port, Name) ->
+ case ftp_host(Config) of
+ {skipped, SkippedReason} ->
+ {skipped, SkippedReason};
+ Host ->
+ TEST_DIR_LEVEL1 = TEST_DIR ++ [create_name(remove_me_dir1)],
+ TEST_DIR_LEVEL2 = TEST_DIR_LEVEL1 ++ [create_name(remove_me_dir2)],
+
+ io:format("<<<<<< CosFileTransfer Testing Configuration >>>>>>~n",[]),
+ io:format("Top Dir: ~p~nLevel2 Dir: ~p~n", [TEST_DIR_LEVEL1, TEST_DIR_LEVEL2]),
+
+ ?line ?match(ok, remote_apply(Node, ?MODULE, install_data,
+ [tcp, {WhichType, Host, Name}])),
+
+ ?line VFS = ?matchnopr({'IOP_IOR',"IDL:omg.org/CosFileTransfer/VirtualFileSystem:1.0",_},
+ corba:string_to_object("corbaname::1.2@localhost:"++integer_to_list(Port)++"/NameService#"++Name)),
+
+ %% Start two File Transfer Sessions (Source and Target).
+ ?line {FS, DirS} = ?matchnopr({{'IOP_IOR',_,_}, _},
+ 'CosFileTransfer_VirtualFileSystem':login(VFS,
+ ?FTP_USER,
+ ?FTP_PASS,
+ ?FTP_ACC)),
+
+ %% Do some basic test on one of the Directories attributes.
+ ?line ?match([_H|_], 'CosFileTransfer_Directory':'_get_name'(DirS)),
+ ?line ?match([_H|_], 'CosFileTransfer_Directory':'_get_complete_file_name'(DirS)),
+ ?line ?match({'IOP_IOR',[],[]}, 'CosFileTransfer_Directory':'_get_parent'(DirS)),
+ ?line ?matchnopr(FS, 'CosFileTransfer_Directory':'_get_associated_session'(DirS)),
+
+ %% Create a Root Directory. Currently we only need to create one but
+ %% later on, when supporting other protocols than FTP it's not enough.
+ ?line Dir1 = 'CosFileTransfer_FileTransferSession':create_directory(FS,
+ TEST_DIR_LEVEL1),
+ io:format("<<<<<< CosFileTransfer Testing Properties >>>>>>~n",[]),
+ ?line ?match({ok, [tk_long, tk_boolean]},
+ 'CosFileTransfer_Directory':get_allowed_property_types(Dir1)),
+ ?line ?match({ok, [_,_]},
+ 'CosFileTransfer_Directory':get_allowed_properties(Dir1)),
+ ?line ?match({'EXCEPTION', _},
+ 'CosFileTransfer_Directory':define_property_with_mode(Dir1,
+ "num_children",
+ #any{typecode=tk_long, value=0},
+ fixed_readonly)),
+ ?line ?match({'EXCEPTION', _},
+ 'CosFileTransfer_Directory':define_property_with_mode(Dir1,
+ "wrong",
+ #any{typecode=tk_long, value=0},
+ fixed_readonly)),
+ ?line ?match({'EXCEPTION', _},
+ 'CosFileTransfer_Directory':define_property_with_mode(Dir1,
+ "num_children",
+ #any{typecode=tk_short, value=0},
+ fixed_readonly)),
+ ?line ?match({'EXCEPTION', _},
+ 'CosFileTransfer_Directory':define_property_with_mode(Dir1,
+ "num_children",
+ #any{typecode=tk_long, value=0},
+ fixed_normal)),
+ ?line ?match({'EXCEPTION', _},
+ 'CosFileTransfer_Directory':define_properties_with_modes(Dir1,
+ [#'CosPropertyService_PropertyDef'
+ {property_name = "num_children",
+ property_value = #any{typecode=tk_long, value=0},
+ property_mode = fixed_readonly}])),
+ ?line ?match(fixed_readonly,
+ 'CosFileTransfer_Directory':get_property_mode(Dir1, "num_children")),
+ ?line ?match({true,
+ [#'CosPropertyService_PropertyMode'{property_name = "num_children",
+ property_mode = fixed_readonly}]},
+ 'CosFileTransfer_Directory':get_property_modes(Dir1, ["num_children"])),
+ ?line ?match({'EXCEPTION', _},
+ 'CosFileTransfer_Directory':set_property_mode(Dir1, "num_children", fixed_readonly)),
+
+ ?line ?match({'EXCEPTION', _},
+ 'CosFileTransfer_Directory':
+ set_property_modes(Dir1,
+ [#'CosPropertyService_PropertyMode'
+ {property_name = "num_children",
+ property_mode = fixed_readonly}])),
+ ?line ?match({'EXCEPTION', _},
+ 'CosFileTransfer_Directory':
+ set_property_modes(Dir1,
+ [#'CosPropertyService_PropertyMode'
+ {property_name = "wrong",
+ property_mode = fixed_readonly}])),
+ ?line ?match({'EXCEPTION', _},
+ 'CosFileTransfer_Directory':
+ set_property_modes(Dir1,
+ [#'CosPropertyService_PropertyMode'
+ {property_name = "num_children",
+ property_mode = fixed_normal}])),
+ ?line ?match({'EXCEPTION', _},
+ 'CosFileTransfer_Directory':define_property(Dir1,
+ "num_children",
+ #any{typecode=tk_long, value=0})),
+ ?line ?match({'EXCEPTION', _},
+ 'CosFileTransfer_Directory':define_property(Dir1,
+ "wrong",
+ #any{typecode=tk_long, value=0})),
+ ?line ?match({'EXCEPTION', _},
+ 'CosFileTransfer_Directory':define_property(Dir1,
+ "num_children",
+ #any{typecode=tk_short, value=0})),
+
+ ?line ?match({'EXCEPTION', _},
+ 'CosFileTransfer_Directory':define_property(Dir1,
+ "num_children",
+ #any{typecode=tk_long, value=0})),
+
+ ?line ?match({'EXCEPTION', _},
+ 'CosFileTransfer_Directory':
+ define_properties(Dir1,
+ [#'CosPropertyService_Property'
+ {property_name = "num_children",
+ property_value = #any{typecode=tk_long,
+ value=0}}])),
+ ?line ?match({'EXCEPTION', _},
+ 'CosFileTransfer_Directory':
+ define_properties(Dir1,
+ [#'CosPropertyService_Property'
+ {property_name = "wrong",
+ property_value = #any{typecode=tk_long,
+ value=0}}])),
+ ?line ?match({'EXCEPTION', _},
+ 'CosFileTransfer_Directory':
+ define_properties(Dir1,
+ [#'CosPropertyService_Property'
+ {property_name = "num_children",
+ property_value = #any{typecode=tk_short,
+ value=0}}])),
+ ?line ?match(2, 'CosFileTransfer_Directory':get_number_of_properties(Dir1)),
+
+ ?line ?match({ok, ["num_children", "is_directory"], {'IOP_IOR',[],[]}},
+ 'CosFileTransfer_Directory':get_all_property_names(Dir1, 2)),
+ ?line ?match({ok, ["is_directory"], _},
+ 'CosFileTransfer_Directory':get_all_property_names(Dir1, 1)),
+
+ ?line ?match(#any{},
+ 'CosFileTransfer_Directory':get_property_value(Dir1, "num_children")),
+ ?line ?match(#any{},
+ 'CosFileTransfer_Directory':get_property_value(Dir1, "is_directory")),
+ ?line ?match({'EXCEPTION', _},
+ 'CosFileTransfer_Directory':get_property_value(Dir1, "wrong")),
+
+ ?line ?match({true,
+ [#'CosPropertyService_Property'{property_name = "num_children"}]},
+ 'CosFileTransfer_Directory':get_properties(Dir1, ["num_children"])),
+ ?line ?match({false,
+ [#'CosPropertyService_Property'{property_name = "wrong"}]},
+ 'CosFileTransfer_Directory':get_properties(Dir1, ["wrong"])),
+
+ ?line ?match({ok, [_],_},
+ 'CosFileTransfer_Directory':get_all_properties(Dir1, 1)),
+ ?line ?match({ok, [_,_], {'IOP_IOR',[],[]}},
+ 'CosFileTransfer_Directory':get_all_properties(Dir1, 2)),
+
+ ?line ?match({'EXCEPTION', _},
+ 'CosFileTransfer_Directory':delete_property(Dir1, "num_children")),
+ ?line ?match({'EXCEPTION', _},
+ 'CosFileTransfer_Directory':delete_property(Dir1, "wrong")),
+
+
+ ?line ?match({'EXCEPTION', _},
+ 'CosFileTransfer_Directory':delete_properties(Dir1, ["num_children"])),
+ ?line ?match({'EXCEPTION', _},
+ 'CosFileTransfer_Directory':delete_properties(Dir1, ["wrong"])),
+ ?line ?match(false, 'CosFileTransfer_Directory':delete_all_properties(Dir1)),
+ ?line ?match(true,
+ 'CosFileTransfer_Directory':is_property_defined(Dir1, "num_children")),
+ ?line ?match(false,
+ 'CosFileTransfer_Directory':is_property_defined(Dir1, "wrong")),
+
+ %% The Top Dir should be empty and ...
+ ?line ?match({ok,[],_}, 'CosFileTransfer_Directory':list(Dir1, 1000)),
+ ?line ?match( #any{value=0},
+ 'CosPropertyService_PropertySet':get_property_value(Dir1, "num_children")),
+ %% Create a sub-directory.
+ ?line Dir2 = 'CosFileTransfer_FileTransferSession':create_directory(FS,
+ TEST_DIR_LEVEL2),
+ ?line ?match( #any{value=1},
+ 'CosPropertyService_PropertySet':get_property_value(Dir1, "num_children")),
+
+ ?line ?match({ok, [_,_], {'IOP_IOR',[],[]}},
+ 'CosFileTransfer_Directory':get_all_properties(Dir1, 2)),
+ ?line {_,_,Iterator1} = ?match({ok, [_], _},
+ 'CosFileTransfer_Directory':get_all_properties(Dir1, 1)),
+ ?line ?match({false, [_]},
+ 'CosPropertyService_PropertiesIterator':next_n(Iterator1,4)),
+
+ ?line {_,_,Iterator0} = ?match({ok, [], _},
+ 'CosFileTransfer_Directory':get_all_properties(Dir1, 0)),
+
+ ?line ?match({false, [_, {'CosPropertyService_Property',
+ "num_children",{any,tk_long,1}}]},
+ 'CosPropertyService_PropertiesIterator':next_n(Iterator0,4)),
+
+ ?line ?match({true,
+ [#'CosPropertyService_Property'{property_name = "num_children"}]},
+ 'CosFileTransfer_Directory':get_properties(Dir1, ["num_children"])),
+
+ %% The Top Directory is not emtpy any more and ...
+ ?line {ok,[#'CosFileTransfer_FileWrapper'{the_file = DirRef}],_} =
+ ?matchnopr({ok,[{'CosFileTransfer_FileWrapper', _, ndirectory}],_},
+ 'CosFileTransfer_Directory':list(Dir1, 1000)),
+ %% ... its name eq. to 'TEST_DIR_LEVEL2'
+ ?line ?match(TEST_DIR_LEVEL2,
+ 'CosFileTransfer_Directory':'_get_complete_file_name'(DirRef)),
+
+ ?line #'CosFileTransfer_FileWrapper'{the_file = Dir3} =
+ ?matchnopr({'CosFileTransfer_FileWrapper', _, ndirectory},
+ 'CosFileTransfer_FileTransferSession':get_file(FS, TEST_DIR_LEVEL1)),
+
+ %% Must get the same result for the 'get_file' operation.
+ ?line {ok,[#'CosFileTransfer_FileWrapper'{the_file = DirRef2}],_} =
+ ?matchnopr({ok,[{'CosFileTransfer_FileWrapper', _, ndirectory}],_},
+ 'CosFileTransfer_Directory':list(Dir3,1000)),
+ ?line ?match(TEST_DIR_LEVEL2,
+ 'CosFileTransfer_Directory':'_get_complete_file_name'(DirRef2)),
+
+ %% Since the top directory isn't empty deleting it must fail.
+ ?line ?match({'EXCEPTION', _},
+ 'CosFileTransfer_FileTransferSession':delete(FS, Dir1)),
+
+ %% Delete the sub-directory and ...
+ ?line ?match(ok, 'CosFileTransfer_FileTransferSession':delete(FS, Dir2)),
+ %% ... see if the top directory realyy is empty.
+ ?line ?match({ok,[],_}, 'CosFileTransfer_Directory':list(Dir1, 1000)),
+
+ ?line ?match(ok, 'CosFileTransfer_FileTransferSession':delete(FS, Dir1)),
+ %% Test if the top directory been removed as intended.
+ ?line ?match({'EXCEPTION', {'CosFileTransfer_FileNotFoundException', _, _}},
+ 'CosFileTransfer_FileTransferSession':get_file(FS, TEST_DIR_LEVEL1)),
+
+ ?line ?match(false, corba_object:non_existent(FS)),
+ ?line ?match(ok, 'CosFileTransfer_FileTransferSession':logout(FS)),
+ %% To make sure Orber can remove it from mnesia.
+ timer:sleep(1000),
+ ?line ?match(true, corba_object:non_existent(FS)),
+ ?line ?match(ok, remote_apply(Node, ?MODULE, uninstall_data, [Name])),
+ stop_orber_remote(Node, normal),
+ ok
+ end.
+
+
+%%-----------------------------------------------------------------
+%% Internal functions
+%%-----------------------------------------------------------------
+ftp_host(Config) ->
+ case ?config(ftp_remote_host, Config) of
+ undefined ->
+ {skipped, "The configuration parameter 'ftp_remote_host' not defined."};
+ Host ->
+ Host
+ end.
+
+loop_files([]) ->
+ io:format("@@@ DONE @@@~n", []);
+loop_files([#'CosFileTransfer_FileWrapper'{the_file = H}|T]) ->
+ FullName = 'CosFileTransfer_File':'_get_complete_file_name'(H),
+ Name = 'CosFileTransfer_File':'_get_name'(H),
+ io:format("FULL NAME: ~p SHORT NAME: ~p~n", [FullName, Name]),
+ loop_files(T).
+
+
+create_file_on_source_node('FTP', _Config, Host, FileName, Path, Data) ->
+ io:format("<<<<<< CosFileTransfer Testing File >>>>>>~n",[]),
+ io:format("Host: ~p~nPath: ~p~nFile: ~p~n", [Host, Path, FileName]),
+ {ok, Pid} = ?match({ok, _}, inets:start(ftpc, [{host, Host}], stand_alone)),
+ ?match(ok, ftp:user(Pid, ?FTP_USER, ?FTP_PASS)),
+ ?match(ok, ftp:cd(Pid, Path)),
+ ?match(ok, ftp:send_bin(Pid, list_to_binary(Data), FileName)),
+ ?match(ok, inets:stop(ftpc, Pid));
+create_file_on_source_node({'NATIVE', _}, _Config, Host, FileName, Path, Data) ->
+ io:format("<<<<<< CosFileTransfer Testing File >>>>>>~n",[]),
+ io:format("Host: ~p~nPath: ~p~nFile: ~p~n", [Host, Path, FileName]),
+ ?match(ok, file:write_file(FileName, list_to_binary(Data))).
+
+create_name(Type) ->
+ {MSec, Sec, USec} = erlang:now(),
+ lists:concat([Type,'_',MSec, '_', Sec, '_', USec]).
+
+
+
+
+%%------------------------------------------------------------
+%% function : create_node/4
+%% Arguments: Name - the name of the new node (atom())
+%% Port - which iiop_port (integer())
+%% Domain - which domain.
+%% Type - if /4 used the types defines the extra arguments
+%% to be used.
+%% Returns : {ok, Node} | {error, _}
+%% Effect : Starts a new slave-node with given (optinally)
+%% extra arguments. If fails it retries 'Retries' times.
+%%------------------------------------------------------------
+create_node(Name, Port, normal) ->
+ Args = basic_args(Name),
+ create_node(Name, Port, 10, normal, Args, []);
+create_node(Name, {Port, _Depth}, ssl) ->
+ Dir = filename:join([code:lib_dir(ssl), "examples", "certs", "etc"]),
+ Args = basic_args(Name),
+ {ok, Node} = create_node(list_to_atom(Name), Port, 10, ssl, Args, []),
+ %% Client
+ rpc:call(Node, application, set_env, [cosFileTransfer, ssl_client_certfile,
+ filename:join([Dir, "client", "cert.pem"])]),
+ rpc:call(Node, application, set_env, [cosFileTransfer, ssl_client_cacertfile,
+ filename:join([Dir, "client", "cacerts.pem"])]),
+ rpc:call(Node, application, set_env, [cosFileTransfer, ssl_client_keyfile,
+ filename:join([Dir, "client", "key.pem"])]),
+ rpc:call(Node, application, set_env, [cosFileTransfer, ssl_client_verify, 1]),
+ rpc:call(Node, application, set_env, [cosFileTransfer, ssl_client_depth, 0]),
+
+ %% Server
+ rpc:call(Node, application, set_env, [cosFileTransfer, ssl_server_certfile,
+ filename:join([Dir, "server", "cert.pem"])]),
+ rpc:call(Node, application, set_env, [cosFileTransfer, ssl_server_cacertfile,
+ filename:join([Dir, "server", "cacerts.pem"])]),
+ rpc:call(Node, application, set_env, [cosFileTransfer, ssl_server_keyfile,
+ filename:join([Dir, "server", "key.pem"])]),
+ rpc:call(Node, application, set_env, [cosFileTransfer, ssl_server_verify, 1]),
+ rpc:call(Node, application, set_env, [cosFileTransfer, ssl_server_depth, 0]),
+ {ok, Node}.
+
+%create_node(Name, {Port, Depth}, ssl) ->
+% TestLibs = filename:join(filename:dirname(code:which(?MODULE)), "ssl_data"),
+% Args = basic_args(Name),
+% SArgs = basic_ssl_args(TestLibs, Args),
+% LArgs = level_based_ssl(Depth, TestLibs, SArgs),
+% create_node(list_to_atom(Name), Port, 10, ssl, LArgs, [{sslpath, TestLibs}]).
+
+create_node(Name, Port, Retries, Type, Args, Options) ->
+ [_, Host] = ?match([_,_],string:tokens(atom_to_list(node()), [$@])),
+ case starter(Host, Name, Args) of
+ {ok, NewNode} ->
+ ?line ?match(pong, net_adm:ping(NewNode)),
+ {ok, Cwd} = file:get_cwd(),
+ Path = code:get_path(),
+ ?line ?match(ok, rpc:call(NewNode, file, set_cwd, [Cwd])),
+ true = rpc:call(NewNode, code, set_path, [Path]),
+ ?match(ok, start_orber_remote(NewNode, Type, Options, Port)),
+ spawn_link(NewNode, ?MODULE, slave_sup, []),
+ rpc:multicall([node() | nodes()], global, sync, []),
+ {ok, NewNode};
+ {error, Reason} when Retries == 0->
+ {error, Reason};
+ {error, Reason} ->
+ io:format("Could not start slavenode ~p ~p retrying~n",
+ [{Host, Name, Args}, Reason]),
+ timer:sleep(500),
+ create_node(Name, Port, Retries - 1, Type, Args, Options)
+ end.
+
+starter(Host, Name, Args) ->
+ case os:type() of
+ vxworks ->
+ test_server:start_node(Name, slave, [{args,Args}]);
+ _ ->
+ slave:start(Host, Name, Args)
+ end.
+
+slave_sup() ->
+ process_flag(trap_exit, true),
+ receive
+ {'EXIT', _, _} ->
+ case os:type() of
+ vxworks ->
+ erlang:halt();
+ _ ->
+ ignore
+ end
+ end.
+
+
+%%------------------------------------------------------------
+%% function : destroy_node
+%% Arguments: Node - which node to destroy.
+%% Type - normal | ssl
+%% Returns :
+%% Effect :
+%%------------------------------------------------------------
+-ifdef(false).
+destroy_node(Node, Type) ->
+ stopper(Node, Type).
+
+stopper(Node, Type) ->
+ catch stop_orber_remote(Node, Type),
+ case os:type() of
+ vxworks ->
+ test_server:stop_node(Node);
+ _ ->
+ slave:stop(Node)
+ end.
+-endif.
+
+%%------------------------------------------------------------
+%% function : remote_apply
+%% Arguments: N - Node, M - Module,
+%% F - Function, A - Arguments (list)
+%% Returns :
+%% Effect :
+%%------------------------------------------------------------
+remote_apply(N, M,F,A) ->
+ case rpc:call(N, M, F, A) of
+ {badrpc, Reason} ->
+ exit(Reason);
+ Other ->
+ Other
+ end.
+
+%%------------------------------------------------------------
+%% function : stop_orber_remote
+%% Arguments: Node - which node to stop orber on.
+%% Type - normal | ssl | light | .......
+%% Returns : ok
+%% Effect : Stops orber on given node and, if specified,
+%% other applications or programs.
+%%------------------------------------------------------------
+stop_orber_remote(Node, ssl) ->
+ rpc:call(Node, ssl, stop, []),
+ rpc:call(Node, crypto, stop, []),
+ orb_rpc_blast(Node, ssl);
+stop_orber_remote(Node, Type) ->
+ orb_rpc_blast(Node, Type).
+
+orb_rpc_blast(Node, _) ->
+ rpc:call(Node, cosFileTransferApp, stop, []),
+ rpc:call(Node, cosProperty, stop, []),
+ rpc:call(Node, cosFileTransferApp, uninstall, []),
+ rpc:call(Node, cosProperty, uninstall, []),
+ rpc:call(Node, orber, jump_stop, []).
+
+%%------------------------------------------------------------
+%% function : start_orber_remote
+%% Arguments: Node - which node to start orber on.
+%% Type - normal | ssl | light | .......
+%% Returns : ok
+%% Effect : Starts orber on given node and, if specified,
+%% other applications or programs.
+%%------------------------------------------------------------
+start_orber_remote(Node, ssl, _Options, Port) ->
+ rpc:call(Node, ssl, start, []),
+ rpc:call(Node, crypto, start, []),
+ rpc:call(Node, ssl, seed, ["testing"]),
+ orb_rpc_setup(Node, ssl, Port);
+start_orber_remote(Node, Type, _, Port) ->
+ orb_rpc_setup(Node, Type, Port).
+
+orb_rpc_setup(Node, _, Port) ->
+ rpc:call(Node, orber, jump_start, [Port]),
+ rpc:call(Node, cosProperty, install, []),
+ rpc:call(Node, cosProperty, start, []),
+ rpc:call(Node, cosFileTransferApp, install, []).
+
+%%--------------- MISC FUNCTIONS -----------------------------
+basic_args(_Name) ->
+ TestLibs = filename:dirname(code:which(?MODULE)),
+ " -orber orber_debug_level 10" ++
+ " -pa " ++
+ TestLibs ++
+ " -pa " ++
+ filename:join(TestLibs, "all_SUITE_data") ++
+ " -pa " ++
+ filename:dirname(code:which(cosFileTransferApp)).
+
+-ifdef(false).
+basic_ssl_args(TestLibs, Args) ->
+% Args ++
+% " -cosFileTransfer ssl_client_certfile \\\"" ++
+% filename:join(TestLibs, "ssl_client_cert.pem") ++
+% "\\\" -cosFileTransfer ssl_server_certfile \\\""++
+% filename:join(TestLibs, "ssl_server_cert.pem")++"\\\"".
+
+ io:format("<<<<<< SSL LIBS ~p >>>>>>~n",[TestLibs]),
+ NewArgs = Args ++
+ " -cosFileTransfer ssl_client_certfile \\\"" ++
+ filename:join(TestLibs, "ssl_client_cert.pem") ++
+ "\\\" -cosFileTransfer ssl_server_certfile \\\""++
+ filename:join(TestLibs, "ssl_server_cert.pem")++"\\\"",
+ io:format("<<<<<< SSL LIBS ARGS ~p >>>>>>~n",[NewArgs]),
+ NewArgs.
+
+level_based_ssl(1, _TestLibs, Args) ->
+ Args;
+level_based_ssl(2, _TestLibs, Args) ->
+ Args.% ++
+% " -cosFileTransfer ssl_server_depth 2 " ++
+% " -cosFileTransfer ssl_client_depth 2 " ++
+% " -cosFileTransfer ssl_server_verify " ++
+% " -cosFileTransfer ssl_client_verify " ++
+% " -cosFileTransfer ssl_server_cacertfile " ++
+% " -cosFileTransfer ssl_client_cacertfile " ++
+
+-endif.
+
+install_data(Protocol, {WhichType, Host, Name}) ->
+ io:format("<<<<<< Starting ~p/~p VFS at ~p/~p>>>>>>~n",
+ [Protocol, WhichType, Host, Name]),
+ %% Create a Virtual File System.
+ ?line VFS = ?match({_,_,_,_,_,_},
+ cosFileTransferApp:create_VFS(WhichType, [], Host, ?FTP_PORT,
+ [{protocol, Protocol}])),
+ NS = corba:resolve_initial_references("NameService"),
+ NC1 = lname_component:set_id(lname_component:create(), Name),
+ N = lname:insert_component(lname:create(), 1, NC1),
+ 'CosNaming_NamingContext':rebind(NS, N, VFS).
+
+uninstall_data(Name) ->
+ ?line VFS = ?match({_,_,_,_,_,_},
+ corba:string_to_object("corbaname:rir:/NameService#"++Name)),
+ ?line ?match(ok, corba:dispose(VFS)),
+ ok.
+
+
+
+%%------------------- EOF MODULE-----------------------------------
diff --git a/lib/cosFileTransfer/vsn.mk b/lib/cosFileTransfer/vsn.mk
index 2700ecb3e3..ef8ee53c5e 100644
--- a/lib/cosFileTransfer/vsn.mk
+++ b/lib/cosFileTransfer/vsn.mk
@@ -1,16 +1 @@
COSFILETRANSFER_VSN = 1.1.10
-
-TICKETS = \
- OTP-8355 \
- OTP-8374
-
-
-TICKETS_1.1.9 = OTP-8201
-
-TICKETS_1.1.8 = OTP-7987
-
-TICKETS_1.1.7 = OTP-7837
-
-TICKETS_1.1.6 = \
- OTP-7595 \
- OTP-7599 \ No newline at end of file
diff --git a/lib/cosNotification/doc/src/notes.xml b/lib/cosNotification/doc/src/notes.xml
index de5a3e5f4c..04c0c2accd 100644
--- a/lib/cosNotification/doc/src/notes.xml
+++ b/lib/cosNotification/doc/src/notes.xml
@@ -31,6 +31,46 @@
<file>notes.xml</file>
</header>
+ <section><title>cosNotification 1.1.15</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Switched from using the deprecated regexp to re instead.</p>
+ <p>
+ Own Id: OTP-8846</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section>
+ <title>cosNotification 1.1.14</title>
+ <section>
+ <title>Improvements and New Features</title>
+ <list type="bulleted">
+ <item>
+ <p>
+ Test suites published.</p>
+ <p>
+ Own Id: OTP-8543 Aux Id:</p>
+ </item>
+ </list>
+ </section>
+
+ <section>
+ <title>Fixed Bugs and Malfunctions</title>
+ <list type="bulleted">
+ <item>
+ <p>Added missing trailing bracket to define in hrl-file.</p>
+ <p>Own Id: OTP-8489 Aux Id:</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
<section>
<title>cosNotification 1.1.14</title>
<section>
@@ -64,15 +104,15 @@
<list type="bulleted">
<item>
<p>Removed superfluous VT in the documentation.</p>
- <p>Own id: OTP-8353 Aux Id:</p>
+ <p>Own Id: OTP-8353 Aux Id:</p>
</item>
<item>
<p>Removed superfluous backslash in the documentation.</p>
- <p>Own id: OTP-8354 Aux Id:</p>
+ <p>Own Id: OTP-8354 Aux Id:</p>
</item>
<item>
<p>The documentation EIX file was not generated.</p>
- <p>Own id: OTP-8355 Aux Id:</p>
+ <p>Own Id: OTP-8355 Aux Id:</p>
</item>
</list>
</section>
@@ -104,7 +144,7 @@
<item>
<p>Obsolete guards, e.g. record vs is_record, has been changed
to avoid compiler warnings.</p>
- <p>Own id: OTP-7987</p>
+ <p>Own Id: OTP-7987</p>
</item>
</list>
</section>
@@ -118,7 +158,7 @@
<list type="bulleted">
<item>
<p>Updated file headers.</p>
- <p>Own id: OTP-7837 Aux Id:</p>
+ <p>Own Id: OTP-7837 Aux Id:</p>
</item>
</list>
</section>
@@ -132,7 +172,7 @@
<list type="bulleted">
<item>
<p>Documentation source included in open source releases.</p>
- <p>Own id: OTP-7595 Aux Id:</p>
+ <p>Own Id: OTP-7595 Aux Id:</p>
</item>
</list>
</section>
@@ -147,7 +187,7 @@
<item>
<p>The CosNotification proxy objects ignored the gcLimit option, instead
the gcTime value was used.</p>
- <p>Own id: OTP-7553 Aux Id:</p>
+ <p>Own Id: OTP-7553 Aux Id:</p>
</item>
</list>
</section>
@@ -161,7 +201,7 @@
<list type="bulleted">
<item>
<p>Updated file headers.</p>
- <p>Own id: OTP-7011</p>
+ <p>Own Id: OTP-7011</p>
</item>
</list>
</section>
@@ -175,7 +215,7 @@
<list type="bulleted">
<item>
<p>The documentation source has been converted from SGML to XML.</p>
- <p>Own id: OTP-6754</p>
+ <p>Own Id: OTP-6754</p>
</item>
</list>
</section>
@@ -189,7 +229,7 @@
<list type="bulleted">
<item>
<p>Minor Makefile changes.</p>
- <p>Own id: OTP-6701</p>
+ <p>Own Id: OTP-6701</p>
</item>
</list>
</section>
@@ -203,7 +243,7 @@
<list type="bulleted">
<item>
<p>Removed some unused code.</p>
- <p>Own id: OTP-6527</p>
+ <p>Own Id: OTP-6527</p>
</item>
</list>
</section>
@@ -219,7 +259,7 @@
<p>A user can now define the QoS EventReliability to be
Persistent. Note, this is only a lightweight version
and events will be lost if a proxy is terminated.</p>
- <p>Own id: OTP-5923</p>
+ <p>Own Id: OTP-5923</p>
</item>
</list>
</section>
@@ -235,7 +275,7 @@
<p>Possible to configure cosNotification not to type check,
by invoking corba_object:is_a/2, supplied IOR:s. When
a type check fails, the feedback has been improved.</p>
- <p>Own id: OTP-5823 Aux Id: seq10143</p>
+ <p>Own Id: OTP-5823 Aux Id: seq10143</p>
</item>
</list>
</section>
@@ -249,7 +289,7 @@
<list type="bulleted">
<item>
<p>The app-file contained duplicated modules.</p>
- <p>Own id: OTP-4976</p>
+ <p>Own Id: OTP-4976</p>
</item>
</list>
</section>
@@ -268,7 +308,7 @@
Interface Repository. It is necessary to re-compile all IDL-files
and use COS-applications, including Orber, compiled with
IC-4.2.</p>
- <p>Own id: OTP-4576</p>
+ <p>Own Id: OTP-4576</p>
</item>
</list>
</section>
diff --git a/lib/cosNotification/src/cosNotification_Filter.erl b/lib/cosNotification/src/cosNotification_Filter.erl
index dd3b5beb93..7201f7d6e2 100644
--- a/lib/cosNotification/src/cosNotification_Filter.erl
+++ b/lib/cosNotification/src/cosNotification_Filter.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -877,9 +877,9 @@ check_wildcard(Types, Which, WC, Domain, Type) ->
end,
check_types(Types, Which, NewWC).
-%% Change '*' to '.*', see regexp:parse/2 documentation.
+%% Change '*' to '.*', see re:compile/1 documentation.
convert_wildcard([], Acc) ->
- case regexp:parse(lists:reverse(Acc)) of
+ case re:compile(lists:reverse(Acc)) of
{ok, Expr} ->
Expr;
_ ->
@@ -900,37 +900,37 @@ match_types(_, _, []) ->
false;
match_types(Domain, Type, [{domain, WCDomain, Type}|T]) ->
L=length(Domain),
- case catch regexp:matches(Domain, WCDomain) of
- {match, []} ->
+ case catch re:run(Domain, WCDomain) of
+ nomatch ->
match_types(Domain, Type, T);
- {match, [{1, L}]} ->
+ {match, [{0, L}]} ->
true;
_->
match_types(Domain, Type, T)
end;
match_types(Domain, Type, [{type, Domain, WCType}|T]) ->
L=length(Type),
- case catch regexp:matches(Type, WCType) of
- {match, []} ->
+ case catch re:run(Type, WCType) of
+ nomatch ->
match_types(Domain, Type, T);
- {match, [{1, L}]} ->
+ {match, [{0, L}]} ->
true;
_->
match_types(Domain, Type, T)
end;
match_types(Domain, Type, [{both, WCDomain, WCType}|T]) ->
L1=length(Domain),
- case catch regexp:matches(Domain, WCDomain) of
- {match, []} ->
+ case catch re:run(Domain, WCDomain) of
+ nomatch ->
match_types(Domain, Type, T);
- {match, [{1, L1}]} ->
+ {match, [{0, L1}]} ->
L2=length(Type),
- case catch regexp:matches(Type, WCType) of
- {match, []} ->
+ case catch re:run(Type, WCType) of
+ nomatch ->
match_types(Domain, Type, T);
- {match, [{1, L2}]} ->
+ {match, [{0, L2}]} ->
true;
- _->
+ _ ->
match_types(Domain, Type, T)
end;
_->
diff --git a/lib/cosNotification/vsn.mk b/lib/cosNotification/vsn.mk
index a19facffd5..cfd5948dfc 100644
--- a/lib/cosNotification/vsn.mk
+++ b/lib/cosNotification/vsn.mk
@@ -1,18 +1 @@
-COSNOTIFICATION_VSN = 1.1.14
-
-TICKETS = OTP-8489 \
- OTP-8543
-
-TICKETS_1.1.13 = OTP-8353 \
- OTP-8354 \
- OTP-8355
-
-TICKETS_1.1.12 = OTP-8201
-
-TICKETS_1.1.11 = OTP-7987
-
-TICKETS_1.1.10 = OTP-7837
-
-TICKETS_1.1.9 = OTP-7595
-
-TICKETS_1.1.8 = OTP-7553
+COSNOTIFICATION_VSN = 1.1.15
diff --git a/lib/cosProperty/vsn.mk b/lib/cosProperty/vsn.mk
index 3d594a8329..ca9a7ca77e 100644
--- a/lib/cosProperty/vsn.mk
+++ b/lib/cosProperty/vsn.mk
@@ -1,13 +1 @@
COSPROPERTY_VSN = 1.1.12
-
-TICKETS = OTP-8543
-
-TICKETS_1.1.11 = OTP-8355
-
-TICKETS_1.1.10 = OTP-8201
-
-TICKETS_1.1.9 = OTP-7987
-
-TICKETS_1.1.8 = OTP-7837
-
-TICKETS_1.1.7 = OTP-7595
diff --git a/lib/cosTime/vsn.mk b/lib/cosTime/vsn.mk
index 9d8057e8db..429613fb61 100644
--- a/lib/cosTime/vsn.mk
+++ b/lib/cosTime/vsn.mk
@@ -1,13 +1 @@
COSTIME_VSN = 1.1.9
-
-TICKETS = OTP-8543
-
-TICKETS_1.1.8 = OTP-8355
-
-TICKETS_1.1.7 = OTP-8201
-
-TICKETS_1.1.6 = OTP-7987
-
-TICKETS_1.1.5 = OTP-7837
-
-TICKETS_1.1.4 = OTP-7595
diff --git a/lib/cosTransactions/vsn.mk b/lib/cosTransactions/vsn.mk
index 34775be7e4..82e46f51dd 100644
--- a/lib/cosTransactions/vsn.mk
+++ b/lib/cosTransactions/vsn.mk
@@ -1,14 +1 @@
COSTRANSACTIONS_VSN = 1.2.10
-
-TICKETS = OTP-8489 \
- OTP-8543
-
-TICKETS_1.2.9 = OTP-8355
-
-TICKETS_1.2.8 = OTP-8201
-
-TICKETS_1.2.7 = OTP-7987
-
-TICKETS_1.2.6 = OTP-7837
-
-TICKETS_1.2.5 = OTP-7595
diff --git a/lib/crypto/c_src/Makefile.in b/lib/crypto/c_src/Makefile.in
index e728db18eb..040adcfd09 100644
--- a/lib/crypto/c_src/Makefile.in
+++ b/lib/crypto/c_src/Makefile.in
@@ -68,13 +68,13 @@ RELSYSDIR = $(RELEASE_PATH)/lib/crypto-$(VSN)
# ----------------------------------------------------
# Misc Macros
# ----------------------------------------------------
-OBJS = $(OBJDIR)/crypto.o
+OBJS = $(OBJDIR)/crypto$(TYPEMARKER).o
NIF_MAKEFILE = $(PRIVDIR)/Makefile
ifeq ($(findstring win32,$(TARGET)), win32)
-NIF_LIB = $(LIBDIR)/crypto.dll
+NIF_LIB = $(LIBDIR)/crypto$(TYPEMARKER).dll
else
-NIF_LIB = $(LIBDIR)/crypto.so
+NIF_LIB = $(LIBDIR)/crypto$(TYPEMARKER).so
endif
ifeq ($(HOST_OS),)
@@ -102,20 +102,30 @@ $(OBJDIR):
$(LIBDIR):
-@mkdir -p $(LIBDIR)
-$(OBJDIR)/%.o: %.c
+$(OBJDIR)/%$(TYPEMARKER).o: %.c
$(INSTALL_DIR) $(OBJDIR)
$(CC) -c -o $@ $(ALL_CFLAGS) $<
-$(LIBDIR)/crypto.so: $(OBJS)
+$(LIBDIR)/crypto$(TYPEMARKER).so: $(OBJS)
$(INSTALL_DIR) $(LIBDIR)
$(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS) $(CRYPTO_LINK_LIB)
-$(LIBDIR)/crypto.dll: $(OBJS)
+$(LIBDIR)/crypto$(TYPEMARKER).dll: $(OBJS)
$(INSTALL_DIR) $(LIBDIR)
$(LD) $(LDFLAGS) -o $@ $(SSL_DED_LD_RUNTIME_LIBRARY_PATH) -L$(SSL_LIBDIR) $(OBJS) -llibeay32
clean:
- rm -f $(NIF_LIB) $(OBJS)
+ifeq ($(findstring win32,$(TARGET)), win32)
+ rm -f $(LIBDIR)/crypto.dll
+ rm -f $(LIBDIR)/crypto.debug.dll
+else
+ rm -f $(LIBDIR)/crypto.so
+ rm -f $(LIBDIR)/crypto.debug.so
+ rm -f $(LIBDIR)/crypto.valgrind.so
+endif
+ rm -f $(OBJDIR)/crypto.o
+ rm -f $(OBJDIR)/crypto.debug.o
+ rm -f $(OBJDIR)/crypto.valgrind.o
rm -f core *~
docs:
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index 68079f06c7..85614a84c2 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -64,8 +64,8 @@
# define ERL_VALGRIND_ASSERT_MEM_DEFINED(ptr,size) \
((void) ((VALGRIND_CHECK_MEM_IS_DEFINED(ptr,size) == 0) ? 1 : \
- (fprintf(stderr,"\r\n####### VALGRIND_ASSSERT(%p,%d) failed at %s:%d\r\n",\
- (ptr),(size), __FILE__, __LINE__), abort(), 0)))
+ (fprintf(stderr,"\r\n####### VALGRIND_ASSSERT(%p,%ld) failed at %s:%d\r\n",\
+ (ptr),(long)(size), __FILE__, __LINE__), abort(), 0)))
#else
# define ERL_VALGRIND_MAKE_MEM_DEFINED(ptr,size)
# define ERL_VALGRIND_ASSERT_MEM_DEFINED(ptr,size)
@@ -706,12 +706,13 @@ static int get_bn_from_mpint(ErlNifEnv* env, ERL_NIF_TERM term, BIGNUM** bnp)
static ERL_NIF_TERM rand_uniform_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Lo,Hi) */
- BIGNUM *bn_from, *bn_to, *bn_rand;
+ BIGNUM *bn_from = NULL, *bn_to, *bn_rand;
unsigned char* data;
unsigned dlen;
ERL_NIF_TERM ret;
if (!get_bn_from_mpint(env, argv[0], &bn_from)
|| !get_bn_from_mpint(env, argv[1], &bn_rand)) {
+ if (bn_from) BN_free(bn_from);
return enif_make_badarg(env);
}
@@ -770,7 +771,7 @@ static int inspect_mpint(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifBinary* bin)
static ERL_NIF_TERM dss_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (DigestType,Data,Signature,Key=[P, Q, G, Y]) */
ErlNifBinary data_bin, sign_bin;
- BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_y;
+ BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL, *dsa_y = NULL;
unsigned char hmacbuf[SHA_DIGEST_LENGTH];
ERL_NIF_TERM head, tail;
DSA *dsa;
@@ -786,6 +787,11 @@ static ERL_NIF_TERM dss_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
|| !enif_get_list_cell(env, tail, &head, &tail)
|| !get_bn_from_mpint(env, head, &dsa_y)
|| !enif_is_empty_list(env,tail)) {
+ badarg:
+ if (dsa_p) BN_free(dsa_p);
+ if (dsa_q) BN_free(dsa_q);
+ if (dsa_g) BN_free(dsa_g);
+ if (dsa_y) BN_free(dsa_y);
return enif_make_badarg(env);
}
if (argv[0] == atom_sha && inspect_mpint(env, argv[1], &data_bin)) {
@@ -796,7 +802,7 @@ static ERL_NIF_TERM dss_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
memcpy(hmacbuf, data_bin.data, SHA_DIGEST_LENGTH);
}
else {
- return enif_make_badarg(env);
+ goto badarg;
}
dsa = DSA_new();
@@ -950,7 +956,7 @@ static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_N
RC4(rc4_key, data.size, data.data,
enif_make_new_binary(env, data.size, &new_data));
- return enif_make_tuple2(env,argv[0],new_data);
+ return enif_make_tuple2(env,new_state,new_data);
}
static ERL_NIF_TERM rc2_40_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -1119,7 +1125,7 @@ static ERL_NIF_TERM rsa_public_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TER
enif_alloc_binary(RSA_size(rsa), &ret_bin);
if (argv[3] == atom_true) {
- ERL_VALGRIND_ASSERT_MEM_DEFINED(buf+i,data_len);
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(data_bin.data,data_bin.size);
i = RSA_public_encrypt(data_bin.size, data_bin.data,
ret_bin.data, rsa, padding);
if (i > 0) {
@@ -1139,6 +1145,7 @@ static ERL_NIF_TERM rsa_public_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TER
return enif_make_binary(env,&ret_bin);
}
else {
+ enif_release_binary(&ret_bin);
return atom_error;
}
}
@@ -1167,7 +1174,7 @@ static ERL_NIF_TERM rsa_private_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TE
enif_alloc_binary(RSA_size(rsa), &ret_bin);
if (argv[3] == atom_true) {
- ERL_VALGRIND_ASSERT_MEM_DEFINED(buf+i,data_len);
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(data_bin.data,data_bin.size);
i = RSA_private_encrypt(data_bin.size, data_bin.data,
ret_bin.data, rsa, padding);
if (i > 0) {
@@ -1187,6 +1194,7 @@ static ERL_NIF_TERM rsa_private_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TE
return enif_make_binary(env,&ret_bin);
}
else {
+ enif_release_binary(&ret_bin);
return atom_error;
}
}
@@ -1266,7 +1274,7 @@ static ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_
|| !enif_get_list_cell(env, tail, &head, &tail)
|| !get_bn_from_mpint(env, head, &dh_params->g)
|| !enif_is_empty_list(env, tail)) {
-
+ DH_free(dh_params);
return enif_make_badarg(env);
}
@@ -1293,7 +1301,7 @@ static ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_
static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (OthersPublicKey, MyPrivateKey, DHParams=[P,G]) */
DH* dh_params = DH_new();
- BIGNUM* pubkey;
+ BIGNUM* pubkey = NULL;
int i;
ErlNifBinary ret_bin;
ERL_NIF_TERM ret, head, tail;
@@ -1321,6 +1329,7 @@ static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T
ret = atom_error;
}
}
+ if (pubkey) BN_free(pubkey);
DH_free(dh_params);
return ret;
}
diff --git a/lib/crypto/doc/src/notes.xml b/lib/crypto/doc/src/notes.xml
index 79798331ca..3c571eb2a3 100644
--- a/lib/crypto/doc/src/notes.xml
+++ b/lib/crypto/doc/src/notes.xml
@@ -30,6 +30,56 @@
</header>
<p>This document describes the changes made to the Crypto application.</p>
+<section><title>Crypto 2.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Crypto dialyzer type error in md5_mac and sha_mac.</p>
+ <p>
+ Own Id: OTP-8718</p>
+ </item>
+ <item>
+ <p>
+ RC4 stream cipher didn't work. This since the new NIF
+ implementation of <c>crypto:rc4_encrypt_with_state/2</c>
+ introduced in <c>crypto-2.0</c> didn't return an updated
+ state. (Thanks to Paul Guyot)</p>
+ <p>
+ Own Id: OTP-8781</p>
+ </item>
+ <item>
+ <p>
+ A number of memory leaks in the crypto NIF library have
+ been fixed.</p>
+ <p>
+ Own Id: OTP-8810</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Added erlang:system_info(build_type) which makes it
+ easier to chose drivers, NIF libraries, etc based on
+ build type of the runtime system.</p>
+ <p>
+ The NIF library for crypto can now be built for valgrind
+ and/or debug as separate NIF libraries that will be
+ automatically loaded if the runtime system has been built
+ with a matching build type.</p>
+ <p>
+ Own Id: OTP-8760</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Crypto 2.0</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 19fa495b7d..71fd91cafd 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -93,22 +93,42 @@
-define(CRYPTO_NIF_VSN,101).
on_load() ->
- LibName = "crypto",
+ LibBaseName = "crypto",
PrivDir = code:priv_dir(crypto),
- Lib1 = filename:join([PrivDir, "lib", LibName]),
- Status = case erlang:load_nif(Lib1, ?CRYPTO_NIF_VSN) of
+ LibName = case erlang:system_info(build_type) of
+ opt ->
+ LibBaseName;
+ Type ->
+ LibTypeName = LibBaseName ++ "." ++ atom_to_list(Type),
+ case (filelib:wildcard(
+ filename:join(
+ [PrivDir,
+ "lib",
+ LibTypeName ++ "*"])) /= []) orelse
+ (filelib:wildcard(
+ filename:join(
+ [PrivDir,
+ "lib",
+ erlang:system_info(system_architecture),
+ LibTypeName ++ "*"])) /= []) of
+ true -> LibTypeName;
+ false -> LibBaseName
+ end
+ end,
+ Lib = filename:join([PrivDir, "lib", LibName]),
+ Status = case erlang:load_nif(Lib, ?CRYPTO_NIF_VSN) of
ok -> ok;
{error, {load_failed, _}}=Error1 ->
- LibDir2 =
+ ArchLibDir =
filename:join([PrivDir, "lib",
erlang:system_info(system_architecture)]),
Candidate =
- filelib:wildcard(filename:join([LibDir2,LibName ++ "*" ])),
+ filelib:wildcard(filename:join([ArchLibDir,LibName ++ "*" ])),
case Candidate of
[] -> Error1;
_ ->
- Lib2 = filename:join([LibDir2, LibName]),
- erlang:load_nif(Lib2, ?CRYPTO_NIF_VSN)
+ ArchLib = filename:join([ArchLibDir, LibName]),
+ erlang:load_nif(ArchLib, ?CRYPTO_NIF_VSN)
end;
Error1 -> Error1
end,
@@ -119,7 +139,6 @@ on_load() ->
"OpenSSL might not be installed on this system.~n",[E,Str]),
Status
end.
-
nif_stub_error(Line) ->
erlang:nif_error({nif_not_loaded,module,?MODULE,line,Line}).
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index 576949d38d..06b284d50d 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -54,6 +54,7 @@
dh/1,
exor_test/1,
rc4_test/1,
+ rc4_stream_test/1,
blowfish_cfb64/1,
smp/1,
cleanup/1]).
@@ -89,6 +90,7 @@ all(suite) ->
dh,
exor_test,
rc4_test,
+ rc4_stream_test,
mod_exp_test,
blowfish_cfb64,
smp],
@@ -979,6 +981,21 @@ rc4_test(Config) when is_list(Config) ->
CT2 = binary_to_list(crypto:rc4_encrypt(K, R2)),
ok.
+rc4_stream_test(doc) ->
+ ["Test rc4 stream encryption ."];
+rc4_stream_test(suite) ->
+ [];
+rc4_stream_test(Config) when is_list(Config) ->
+ CT1 = <<"hej">>,
+ CT2 = <<" p� dig">>,
+ K = "apaapa",
+ State0 = crypto:rc4_set_key(K),
+ {State1, R1} = crypto:rc4_encrypt_with_state(State0, CT1),
+ {_State2, R2} = crypto:rc4_encrypt_with_state(State1, CT2),
+ R = list_to_binary([R1, R2]),
+ <<71,112,14,44,140,33,212,144,155,47>> = R,
+ ok.
+
blowfish_cfb64(doc) -> ["Test Blowfish encrypt/decrypt."];
blowfish_cfb64(suite) -> [];
blowfish_cfb64(Config) when is_list(Config) ->
@@ -1029,7 +1046,7 @@ worker_loop(0, _) ->
worker_loop(N, Config) ->
Funcs = { md5, md5_update, md5_mac, md5_mac_io, sha, sha_update, des_cbc,
aes_cfb, aes_cbc, des_cbc_iter, rand_uniform_test,
- rsa_verify_test, exor_test, rc4_test, mod_exp_test },
+ rsa_verify_test, exor_test, rc4_test, rc4_stream_test, mod_exp_test },
F = element(random:uniform(size(Funcs)),Funcs),
%%io:format("worker ~p calling ~p\n",[self(),F]),
diff --git a/lib/crypto/vsn.mk b/lib/crypto/vsn.mk
index d04736fc2b..e3549f0c50 100644
--- a/lib/crypto/vsn.mk
+++ b/lib/crypto/vsn.mk
@@ -1 +1 @@
-CRYPTO_VSN = 2.0
+CRYPTO_VSN = 2.0.1
diff --git a/lib/debugger/doc/src/notes.xml b/lib/debugger/doc/src/notes.xml
index c5f611b8f3..c72a5271ba 100644
--- a/lib/debugger/doc/src/notes.xml
+++ b/lib/debugger/doc/src/notes.xml
@@ -32,6 +32,22 @@
<p>This document describes the changes made to the Debugger
application.</p>
+<section><title>Debugger 3.2.4</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Type specs have been added/cleaned up. (Thanks to Kostis
+ Sagonas.)</p>
+ <p>
+ Own Id: OTP-8757</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Debugger 3.2.3</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/debugger/src/dbg_debugged.erl b/lib/debugger/src/dbg_debugged.erl
index b56ebef14a..3732c40c73 100644
--- a/lib/debugger/src/dbg_debugged.erl
+++ b/lib/debugger/src/dbg_debugged.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,6 +19,8 @@
-module(dbg_debugged).
%% External exports
+%% Avoid warning for local function demonitor/1 clashing with autoimported BIF.
+-compile({no_auto_import,[demonitor/1]}).
-export([eval/3]).
%%====================================================================
diff --git a/lib/debugger/test/Makefile b/lib/debugger/test/Makefile
new file mode 100644
index 0000000000..ac929038f7
--- /dev/null
+++ b/lib/debugger/test/Makefile
@@ -0,0 +1,106 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 1998-2010. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+
+MODULES= \
+ andor_SUITE \
+ bs_bincomp_SUITE \
+ bs_construct_SUITE \
+ bs_match_bin_SUITE \
+ bs_match_int_SUITE \
+ bs_match_misc_SUITE \
+ bs_match_tail_SUITE \
+ bs_utf_SUITE \
+ bug_SUITE \
+ erl_eval_SUITE \
+ dbg_ui_SUITE \
+ debugger_SUITE \
+ int_SUITE \
+ int_break_SUITE \
+ int_eval_SUITE \
+ guard_SUITE \
+ exception_SUITE \
+ fun_SUITE \
+ lc_SUITE \
+ record_SUITE \
+ trycatch_SUITE \
+ test_lib \
+ cleanup
+
+ERL_FILES= $(MODULES:%=%.erl)
+
+TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+INSTALL_PROGS= $(TARGET_FILES)
+
+EMAKEFILE=Emakefile
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/debugger_test
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+
+ERL_MAKE_FLAGS +=
+ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include
+
+EBIN = .
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+make_emakefile:
+ $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES) \
+ > $(EMAKEFILE)
+ $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) '*_SUITE_make' \
+ >> $(EMAKEFILE)
+
+tests debug opt: make_emakefile
+ erl $(ERL_MAKE_FLAGS) -make
+
+clean:
+ rm -f $(EMAKEFILE)
+ rm -f $(TARGET_FILES) $(GEN_FILES)
+ rm -f core
+
+docs:
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_spec: opt
+
+release_tests_spec: make_emakefile
+ $(INSTALL_DIR) $(RELSYSDIR)
+ $(INSTALL_DATA) $(EMAKEFILE) $(ERL_FILES) $(RELSYSDIR)
+ $(INSTALL_DATA) debugger.spec $(RELSYSDIR)
+ chmod -f -R u+w $(RELSYSDIR)
+ @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+
+release_docs_spec:
diff --git a/lib/debugger/test/andor_SUITE.erl b/lib/debugger/test/andor_SUITE.erl
new file mode 100644
index 0000000000..3482a22a34
--- /dev/null
+++ b/lib/debugger/test/andor_SUITE.erl
@@ -0,0 +1,305 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-module(andor_SUITE).
+
+-export([all/1,init_per_testcase/2,fin_per_testcase/2,init_all/1,finish_all/1,
+ t_andalso/1,t_orelse/1,inside/1,overlap/1,
+ combined/1,in_case/1]).
+
+-include("test_server.hrl").
+
+all(suite) ->
+ [{conf,init_all,cases(),finish_all}].
+
+init_per_testcase(_Case, Config) ->
+ test_lib:interpret(?MODULE),
+ ?line Dog = test_server:timetrap(?t:minutes(1)),
+ [{watchdog,Dog}|Config].
+
+fin_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+init_all(Config) when is_list(Config) ->
+ ?line test_lib:interpret(?MODULE),
+ ?line true = lists:member(?MODULE, int:interpreted()),
+ ok.
+
+finish_all(Config) when is_list(Config) ->
+ ok.
+
+cases() ->
+ [t_andalso,t_orelse,inside,overlap,combined,in_case].
+
+t_andalso(Config) when is_list(Config) ->
+ Bs = [true,false],
+ Ps = [{X,Y} || X <- Bs, Y <- Bs],
+ lists:foreach(fun (P) -> t_andalso_1(P) end, Ps),
+
+ ?line true = true andalso true,
+ ?line false = true andalso false,
+ ?line false = false andalso true,
+ ?line false = false andalso false,
+
+ ?line false = false andalso glurf,
+ ?line false = false andalso exit(exit_now),
+
+ ?line true = not id(false) andalso not id(false),
+ ?line false = not id(false) andalso not id(true),
+ ?line false = not id(true) andalso not id(false),
+ ?line false = not id(true) andalso not id(true),
+
+ ?line {'EXIT',{badarg,_}} = (catch not id(glurf) andalso id(true)),
+ ?line {'EXIT',{badarg,_}} = (catch not id(false) andalso not id(glurf)),
+ ?line false = id(false) andalso not id(glurf),
+ ?line false = false andalso not id(glurf),
+
+ ok.
+
+t_orelse(Config) when is_list(Config) ->
+ Bs = [true,false],
+ Ps = [{X,Y} || X <- Bs, Y <- Bs],
+ lists:foreach(fun (P) -> t_orelse_1(P) end, Ps),
+
+ ?line true = true orelse true,
+ ?line true = true orelse false,
+ ?line true = false orelse true,
+ ?line false = false orelse false,
+
+ ?line true = true orelse glurf,
+ ?line true = true orelse exit(exit_now),
+
+ ?line true = not id(false) orelse not id(false),
+ ?line true = not id(false) orelse not id(true),
+ ?line true = not id(true) orelse not id(false),
+ ?line false = not id(true) orelse not id(true),
+
+ ?line {'EXIT',{badarg,_}} = (catch not id(glurf) orelse id(true)),
+ ?line {'EXIT',{badarg,_}} = (catch not id(true) orelse not id(glurf)),
+ ?line true = id(true) orelse not id(glurf),
+ ?line true = true orelse not id(glurf),
+
+ ok.
+
+t_andalso_1({X,Y}) ->
+ io:fwrite("~w andalso ~w: ",[X,Y]),
+ V1 = echo(X) andalso echo(Y),
+ V1 = if
+ X andalso Y -> true;
+ true -> false
+ end,
+ check(V1, X and Y).
+
+t_orelse_1({X,Y}) ->
+ io:fwrite("~w orelse ~w: ",[X,Y]),
+ V1 = echo(X) orelse echo(Y),
+ V1 = if
+ X orelse Y -> true;
+ true -> false
+ end,
+ check(V1, X or Y).
+
+inside(Config) when is_list(Config) ->
+ ?line true = inside(-8, 1),
+ ?line false = inside(-53.5, -879798),
+ ?line false = inside(1.0, -879),
+ ?line false = inside(59, -879),
+ ?line false = inside(-11, 1.0),
+ ?line false = inside(100, 0.2),
+ ?line false = inside(100, 1.2),
+ ?line false = inside(-53.5, 4),
+ ?line false = inside(1.0, 5.3),
+ ?line false = inside(59, 879),
+ ok.
+
+inside(Xm, Ym) ->
+ X = -10.0,
+ Y = -2.0,
+ W = 20.0,
+ H = 4.0,
+ Res = inside(Xm, Ym, X, Y, W, H),
+ Res = if
+ X =< Xm andalso Xm < X+W andalso Y =< Ym andalso Ym < Y+H -> true;
+ true -> false
+ end,
+ case not id(Res) of
+ Outside ->
+ Outside = if
+ not(X =< Xm andalso Xm < X+W andalso Y =< Ym andalso Ym < Y+H) -> true;
+ true -> false
+ end
+ end,
+ {Res,Xm,Ym,X,Y,W,H} = inside_guard(Xm, Ym, X, Y, W, H),
+ io:format("~p =< ~p andalso ~p < ~p andalso ~p =< ~p andalso ~p < ~p ==> ~p",
+ [X,Xm,Xm,X+W,Y,Ym,Ym,Y+H,Res]),
+ Res.
+
+inside(Xm, Ym, X, Y, W, H) ->
+ X =< Xm andalso Xm < X+W andalso Y =< Ym andalso Ym < Y+H.
+
+inside_guard(Xm, Ym, X, Y, W, H) when X =< Xm andalso Xm < X+W
+ andalso Y =< Ym andalso Ym < Y+H ->
+ {true,Xm,Ym,X,Y,W,H};
+inside_guard(Xm, Ym, X, Y, W, H) ->
+ {false,Xm,Ym,X,Y,W,H}.
+
+overlap(Config) when is_list(Config) ->
+ ?line true = overlap(7.0, 2.0, 8.0, 0.5),
+ ?line true = overlap(7.0, 2.0, 8.0, 2.5),
+ ?line true = overlap(7.0, 2.0, 5.3, 2),
+ ?line true = overlap(7.0, 2.0, 0.0, 100.0),
+
+ ?line false = overlap(-1, 2, -35, 0.5),
+ ?line false = overlap(-1, 2, 777, 0.5),
+ ?line false = overlap(-1, 2, 2, 10),
+ ?line false = overlap(2, 10, 12, 55.3),
+ ok.
+
+overlap(Pos1, Len1, Pos2, Len2) ->
+ Res = case Pos1 of
+ Pos1 when (Pos2 =< Pos1 andalso Pos1 < Pos2+Len2)
+ orelse (Pos1 =< Pos2 andalso Pos2 < Pos1+Len1) ->
+ true;
+ Pos1 -> false
+ end,
+ Res = (Pos2 =< Pos1 andalso Pos1 < Pos2+Len2)
+ orelse (Pos1 =< Pos2 andalso Pos2 < Pos1+Len1),
+ Res = case Pos1 of
+ Pos1 when (Pos2 =< Pos1 andalso Pos1 < Pos2+Len2)
+ orelse (Pos1 =< Pos2 andalso Pos2 < Pos1+Len1) ->
+ true;
+ Pos1 -> false
+ end,
+ id(Res).
+
+
+-define(COMB(A,B,C), (A andalso B orelse C)).
+
+combined(Config) when is_list(Config) ->
+ ?line false = comb(false, false, false),
+ ?line true = comb(false, false, true),
+ ?line false = comb(false, true, false),
+ ?line true = comb(false, true, true),
+
+ ?line false = comb(true, false, false),
+ ?line true = comb(true, true, false),
+ ?line true = comb(true, false, true),
+ ?line true = comb(true, true, true),
+
+ ?line false = comb(false, blurf, false),
+ ?line true = comb(false, blurf, true),
+ ?line true = comb(true, true, blurf),
+
+ ?line false = ?COMB(false, false, false),
+ ?line true = ?COMB(false, false, true),
+ ?line false = ?COMB(false, true, false),
+ ?line true = ?COMB(false, true, true),
+
+ ?line false = ?COMB(true, false, false),
+ ?line true = ?COMB(true, true, false),
+ ?line true = ?COMB(true, false, true),
+ ?line true = ?COMB(true, true, true),
+
+ ?line false = ?COMB(false, blurf, false),
+ ?line true = ?COMB(false, blurf, true),
+ ?line true = ?COMB(true, true, blurf),
+
+ ok.
+-undef(COMB).
+
+comb(A, B, C) ->
+ Res = A andalso B orelse C,
+ Res = if
+ A andalso B orelse C -> true;
+ true -> false
+ end,
+ NotRes = if
+ not(A andalso B orelse C) -> true;
+ true -> false
+ end,
+ NotRes = id(not Res),
+ Res = A andalso B orelse C,
+ Res = if
+ A andalso B orelse C -> true;
+ true -> false
+ end,
+ NotRes = id(not Res),
+ Res = if
+ A andalso B orelse C -> true;
+ true -> false
+ end,
+ id(Res).
+
+%% Test that a boolean expression in a case expression is properly
+%% optimized (in particular, that the error behaviour is correct).
+in_case(Config) when is_list(Config) ->
+ ?line edge_rings = in_case_1(1, 1, 1, 1, 1),
+ ?line not_loop = in_case_1(0.5, 1, 1, 1, 1),
+ ?line loop = in_case_1(0.5, 0.9, 1.1, 1, 4),
+ ?line {'EXIT',{badarith,_}} = (catch in_case_1(1, 1, 1, 1, 0)),
+ ?line {'EXIT',{badarith,_}} = (catch in_case_1(1, 1, 1, 1, nan)),
+ ?line {'EXIT',{badarg,_}} = (catch in_case_1(1, 1, 1, blurf, 1)),
+ ?line {'EXIT',{badarith,_}} = (catch in_case_1([nan], 1, 1, 1, 1)),
+ ok.
+
+in_case_1(LenUp, LenDw, LenN, Rotation, Count) ->
+ Res = in_case_1_body(LenUp, LenDw, LenN, Rotation, Count),
+ Res = in_case_1_guard(LenUp, LenDw, LenN, Rotation, Count),
+ Res.
+
+in_case_1_body(LenUp, LenDw, LenN, Rotation, Count) ->
+ case (LenUp/Count > 0.707) and (LenN/Count > 0.707) and
+ (abs(Rotation) > 0.707) of
+ true ->
+ edge_rings;
+ false ->
+ case (LenUp >= 1) or (LenDw >= 1) or
+ (LenN =< 1) or (Count < 4) of
+ true ->
+ not_loop;
+ false ->
+ loop
+ end
+ end.
+
+in_case_1_guard(LenUp, LenDw, LenN, Rotation, Count) ->
+ case (LenUp/Count > 0.707) andalso (LenN/Count > 0.707) andalso
+ (abs(Rotation) > 0.707) of
+ true -> edge_rings;
+ false when LenUp >= 1 orelse LenDw >= 1 orelse
+ LenN =< 1 orelse Count < 4 -> not_loop;
+ false -> loop
+ end.
+
+check(V1, V0) ->
+ if V1 /= V0 ->
+ io:fwrite("error: ~w.\n", [V1]),
+ ?t:fail();
+ true ->
+ io:fwrite("ok: ~w.\n", [V1])
+ end.
+
+echo(X) ->
+ io:fwrite("eval(~w); ",[X]),
+ X.
+
+id(I) -> I.
diff --git a/lib/debugger/test/bs_bincomp_SUITE.erl b/lib/debugger/test/bs_bincomp_SUITE.erl
new file mode 100644
index 0000000000..8ca2b36f1c
--- /dev/null
+++ b/lib/debugger/test/bs_bincomp_SUITE.erl
@@ -0,0 +1,106 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Originally based on Per Gustafsson's test suite.
+%%
+
+-module(bs_bincomp_SUITE).
+
+-export([all/1,init_per_testcase/2,fin_per_testcase/2,
+ byte_aligned/1,bit_aligned/1,extended_byte_aligned/1,
+ extended_bit_aligned/1,mixed/1]).
+
+-include("test_server.hrl").
+
+init_per_testcase(_Case, Config) ->
+ test_lib:interpret(?MODULE),
+ Dog = test_server:timetrap(?t:minutes(1)),
+ [{watchdog,Dog}|Config].
+
+fin_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+all(suite) ->
+ [byte_aligned,bit_aligned,extended_byte_aligned,
+ extended_bit_aligned,mixed].
+
+
+byte_aligned(Config) when is_list(Config) ->
+ ?line <<"abcdefg">> = << <<(X+32)>> || <<X>> <= <<"ABCDEFG">> >>,
+ ?line <<1:32/little,2:32/little,3:32/little,4:32/little>> =
+ << <<X:32/little>> || <<X:32>> <= <<1:32,2:32,3:32,4:32>> >>,
+ ?line <<1:32/little,2:32/little,3:32/little,4:32/little>> =
+ << <<X:32/little>> || <<X:16>> <= <<1:16,2:16,3:16,4:16>> >>,
+ ok.
+
+bit_aligned(Config) when is_list(Config) ->
+ ?line <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>> =
+ << <<(X+32):7>> || <<X>> <= <<"ABCDEFG">> >>,
+ ?line <<"ABCDEFG">> =
+ << <<(X-32)>> || <<X:7>> <= <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>> >>,
+ ?line <<1:31/little,2:31/little,3:31/little,4:31/little>> =
+ << <<X:31/little>> || <<X:31>> <= <<1:31,2:31,3:31,4:31>> >>,
+ ?line <<1:31/little,2:31/little,3:31/little,4:31/little>> =
+ << <<X:31/little>> || <<X:15>> <= <<1:15,2:15,3:15,4:15>> >>,
+ ok.
+
+extended_byte_aligned(Config) when is_list(Config) ->
+ ?line <<"abcdefg">> = << <<(X+32)>> || X <- "ABCDEFG" >>,
+ ?line "abcdefg" = [(X+32) || <<X>> <= <<"ABCDEFG">>],
+ ?line <<1:32/little,2:32/little,3:32/little,4:32/little>> =
+ << <<X:32/little>> || X <- [1,2,3,4] >>,
+ ?line [256,512,768,1024] =
+ [X || <<X:16/little>> <= <<1:16,2:16,3:16,4:16>>],
+ ok.
+
+extended_bit_aligned(Config) when is_list(Config) ->
+ ?line <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>> =
+ << <<(X+32):7>> || X <- "ABCDEFG" >>,
+ ?line "ABCDEFG" = [(X-32) || <<X:7>> <= <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>>],
+ ?line <<1:31/little,2:31/little,3:31/little,4:31/little>> =
+ << <<X:31/little>> || X <- [1,2,3,4] >>,
+ ?line [256,512,768,1024] =
+ [X || <<X:15/little>> <= <<1:15,2:15,3:15,4:15>>],
+ ok.
+
+mixed(Config) when is_list(Config) ->
+ ?line <<2,3,3,4,4,5,5,6>> =
+ << <<(X+Y)>> || <<X>> <= <<1,2,3,4>>, <<Y>> <= <<1,2>> >>,
+ ?line <<2,3,3,4,4,5,5,6>> =
+ << <<(X+Y)>> || <<X>> <= <<1,2,3,4>>, Y <- [1,2] >>,
+ ?line <<2,3,3,4,4,5,5,6>> =
+ << <<(X+Y)>> || X <- [1,2,3,4], Y <- [1,2] >>,
+ ?line [2,3,3,4,4,5,5,6] =
+ [(X+Y) || <<X>> <= <<1,2,3,4>>, <<Y>> <= <<1,2>>],
+ ?line [2,3,3,4,4,5,5,6] =
+ [(X+Y) || <<X>> <= <<1,2,3,4>>, Y <- [1,2]],
+ ?line <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> =
+ << <<(X+Y):3>> || <<X:3>> <= <<1:3,2:3,3:3,4:3>>, <<Y:3>> <= <<1:3,2:3>> >>,
+ ?line <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> =
+ << <<(X+Y):3>> || <<X:3>> <= <<1:3,2:3,3:3,4:3>>, Y <- [1,2] >>,
+ ?line <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> =
+ << <<(X+Y):3>> || X <- [1,2,3,4], Y <- [1,2] >>,
+ ?line [2,3,3,4,4,5,5,6] =
+ [(X+Y) || <<X:3>> <= <<1:3,2:3,3:3,4:3>>, <<Y:3>> <= <<1:3,2:3>>],
+ ?line [2,3,3,4,4,5,5,6] =
+ [(X+Y) || <<X:3>> <= <<1:3,2:3,3:3,4:3>>, Y <- [1,2]],
+ ok.
diff --git a/lib/debugger/test/bs_construct_SUITE.erl b/lib/debugger/test/bs_construct_SUITE.erl
new file mode 100644
index 0000000000..efc125c582
--- /dev/null
+++ b/lib/debugger/test/bs_construct_SUITE.erl
@@ -0,0 +1,432 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2000-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(bs_construct_SUITE).
+
+-export([all/1,init_per_testcase/2,fin_per_testcase/2,init_all/1,finish_all/1,
+ test1/1, test2/1, test3/1, test4/1, test5/1, testf/1, not_used/1, in_guard/1,
+ coerce_to_float/1]).
+
+-include("test_server.hrl").
+
+all(suite) ->
+ [{conf,init_all,cases(),finish_all}].
+
+cases() ->
+ [test1, test2, test3, test4, test5, testf,
+ not_used, in_guard, coerce_to_float].
+
+init_per_testcase(_Case, Config) ->
+ test_lib:interpret(?MODULE),
+ Dog = test_server:timetrap(?t:minutes(1)),
+ [{watchdog,Dog}|Config].
+
+fin_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+init_all(Config) when is_list(Config) ->
+ ?line test_lib:interpret(?MODULE),
+ ?line true = lists:member(?MODULE, int:interpreted()),
+ ok.
+
+finish_all(Config) when is_list(Config) ->
+ ok.
+
+big(1) ->
+ 57285702734876389752897683.
+
+i(X) -> X.
+
+r(L) ->
+ lists:reverse(L).
+
+-define(T(B, L), {B, ??B, L}).
+-define(N(B), {B, ??B, unknown}).
+
+-define(FAIL(Expr), ?line {'EXIT',{badarg,_}} = (catch Expr)).
+
+l(I_13, I_big1) ->
+ [
+ ?T(<<-43>>,
+ [256-43]),
+ ?T(<<56>>,
+ [56]),
+ ?T(<<1,2>>,
+ [1, 2]),
+ ?T(<<4:4, 7:4>>,
+ [4*16+7]),
+ ?T(<<777:16/big>>,
+ [3, 9]),
+ ?T(<<777:16/little>>,
+ [9, 3]),
+ ?T(<<0.0:32/float>>,
+ [0,0,0,0]),
+ ?T(<<0.125:32/float>>,
+ [62,0,0,0]),
+ ?T(<<0.125:32/little-float>>,
+ [0,0,0,62]),
+ ?T(<<I_big1:32>>,
+ [138, 99, 0, 147]),
+ ?T(<<57285702734876389752897684:32>>,
+ [138, 99, 0, 148]),
+ ?T(<<I_big1:32/little>>,
+ r([138, 99, 0, 147])),
+ ?T(<<-1:17/unit:8>>,
+ lists:duplicate(17, 255)),
+
+ ?T(<<I_13>>,
+ [13]),
+
+ ?T(<<4:8/unit:2,5:2/unit:8>>,
+ [0, 4, 0, 5]),
+
+ ?T(<<1:1, 0:6, 1:1>>,
+ [129]),
+ ?T(<<1:1/little, 0:6/little, 1:1/little>>,
+ [129]),
+
+ ?T(<<<<1,2>>/binary>>,
+ [1, 2]),
+ ?T(<<<<1,2>>:1/binary>>,
+ [1]),
+ ?T(<<4,3,<<1,2>>:1/binary>>,
+ [4,3,1]),
+
+ ?T(<<(256*45+47)>>,
+ [47]),
+
+ ?T(<<57:0>>,
+ []),
+
+ ?T(<<"apa">>,
+ "apa"),
+
+ ?T(<<1:3,"string",9:5>>,
+ [46,110,142,77,45,204,233]),
+
+ ?T(<<>>,
+ []),
+
+ ?T(<<37.98:64/native-float>>,
+ native_3798()),
+
+ ?T(<<32978297842987249827298387697777669766334937:128/native-integer>>,
+ native_bignum())
+
+ ].
+
+native_3798() ->
+ case <<1:16/native>> of
+ <<0,1>> -> [64,66,253,112,163,215,10,61];
+ <<1,0>> -> [61,10,215,163,112,253,66,64]
+ end.
+
+native_bignum() ->
+ case <<1:16/native>> of
+ <<0,1>> -> [129,205,18,177,1,213,170,101,39,231,109,128,176,11,73,217];
+ <<1,0>> -> [217,73,11,176,128,109,231,39,101,170,213,1,177,18,205,129]
+ end.
+
+evaluate(Str, Vars) ->
+ {ok,Tokens,_} =
+ erl_scan:string(Str ++ " . "),
+ {ok, [Expr]} = erl_parse:parse_exprs(Tokens),
+ case erl_eval:expr(Expr, Vars) of
+ {value, Result, _} ->
+ Result
+ end.
+
+eval_list([], _Vars) ->
+ [];
+eval_list([{C_bin, Str, Bytes} | Rest], Vars) ->
+ case catch evaluate(Str, Vars) of
+ {'EXIT', Error} ->
+ io:format("Evaluation error: ~p, ~p, ~p~n", [Str, Vars, Error]),
+ exit(Error);
+ E_bin ->
+ [{C_bin, E_bin, Str, Bytes} | eval_list(Rest, Vars)]
+ end.
+
+one_test({C_bin, E_bin, Str, Bytes}) when list(Bytes) ->
+ io:format(" ~s, ~p~n", [Str, Bytes]),
+ Bin = list_to_binary(Bytes),
+ if
+ C_bin == Bin ->
+ ok;
+ true ->
+ io:format("ERROR: Compiled: ~p. Expected ~p. Got ~p.~n",
+ [Str, Bytes, binary_to_list(C_bin)]),
+ test_server:fail(comp)
+ end,
+ if
+ E_bin == Bin ->
+ ok;
+ true ->
+ io:format("ERROR: Interpreted: ~p. Expected ~p. Got ~p.~n",
+ [Str, Bytes, binary_to_list(E_bin)]),
+ test_server:fail(comp)
+ end;
+one_test({C_bin, E_bin, Str, Result}) ->
+ io:format(" ~s ~p~n", [Str, C_bin]),
+ if
+ C_bin == E_bin ->
+ ok;
+ true ->
+ Arbitrary = case Result of
+ unknown ->
+ size(C_bin);
+ _ ->
+ Result
+ end,
+ case equal_lists(binary_to_list(C_bin),
+ binary_to_list(E_bin),
+ Arbitrary) of
+ false ->
+ io:format("ERROR: Compiled not equal to interpreted:"
+ "~n ~p, ~p.~n",
+ [binary_to_list(C_bin), binary_to_list(E_bin)]),
+ test_server:fail(comp);
+ 0 ->
+ ok;
+ %% For situations where the final bits may not matter, like
+ %% for floats:
+ N when integer(N) ->
+ io:format("Info: compiled and interpreted differ in the"
+ " last bytes:~n ~p, ~p.~n",
+ [binary_to_list(C_bin), binary_to_list(E_bin)]),
+ ok
+ end
+ end.
+
+equal_lists([], [], _) ->
+ 0;
+equal_lists([], _, _) ->
+ false;
+equal_lists(_, [], _) ->
+ false;
+equal_lists([A|AR], [A|BR], R) ->
+ equal_lists(AR, BR, R);
+equal_lists(A, B, R) ->
+ if
+ length(A) /= length(B) ->
+ false;
+ length(A) =< R ->
+ R;
+ true ->
+ false
+ end.
+
+%%% Simple working cases
+test1(suite) -> [];
+test1(Config) when list(Config) ->
+ ?line I_13 = i(13),
+ ?line I_big1 = big(1),
+ ?line Vars = [{'I_13', I_13},
+ {'I_big1', I_big1}],
+ ?line lists:foreach(fun one_test/1, eval_list(l(I_13, I_big1), Vars)).
+
+%%% Misc
+
+%%% <<A:S, A:(N-S)>>
+comp(N, A, S) ->
+ M1 = (1 bsl S) - 1,
+ M2 = (1 bsl (N-S)) - 1,
+ [((A band M1) bsl (N-S)) bor (A band M2)].
+
+gen(N, S, A) ->
+ [?T(<<A:S, A:(N-S)>>, comp(N, A, S))].
+
+gen_l(N, S, A) ->
+ [?T(<<A:S/little, A:(N-S)/little>>, comp(N, A, S))].
+
+test2(suite) -> [];
+test2(Config) when list(Config) ->
+ ?line test2(0, 8, 2#10101010101010101),
+ ?line test2(0, 8, 2#1111111111).
+
+test2(End, End, _) ->
+ ok;
+test2(I, End, A) ->
+ test2(I, A),
+ test2(I+1, End, A).
+
+test2(S, A) ->
+ N = 8,
+ Vars = [{'A',A}, {'N',N}, {'S',S}],
+ io:format("Vars: ~p\n", [Vars]),
+ lists:foreach(fun one_test/1, eval_list(gen(N, S, A), Vars)),
+ lists:foreach(fun one_test/1, eval_list(gen_l(N, S, A), Vars)).
+
+%%% Tests without facit
+
+t3() ->
+ [?N(<<4711:13, 9876:13, 3:6>>),
+ ?N(<<4.57:64/float>>),
+ ?N(<<4.57:32/float>>),
+
+ ?N(<<>>)
+ ].
+
+test3(suite) -> [];
+test3(Config) when list(Config) ->
+ ?line Vars = [],
+ ?line lists:foreach(fun one_test/1, eval_list(t3(), Vars)).
+
+gen_u(N, S, A) ->
+ [?N(<<A:S, A:(N-S)>>)].
+
+gen_u_l(N, S, A) ->
+ [?N(<<A:S/little, A:(N-S)/little>>)].
+
+test4(suite) -> [];
+test4(Config) when list(Config) ->
+ ?line test4(0, 16, 2#10101010101010101),
+ ?line test4(0, 16, 2#1111111111).
+
+test4(End, End, _) ->
+ ok;
+test4(I, End, A) ->
+ test4(I, A),
+ test4(I+1, End, A).
+
+test4(S, A) ->
+ N = 16,
+ Vars = [{'A', A}, {'N', 16}, {'S', S}],
+ lists:foreach(fun one_test/1, eval_list(gen_u(N, S, A), Vars)),
+ lists:foreach(fun one_test/1, eval_list(gen_u_l(N, S, A), Vars)).
+
+gen_b(N, S, A) ->
+ [?T(<<A:S/binary-unit:1, A:(N-S)/binary-unit:1>>,
+ binary_to_list(<<A:S/binary-unit:1, A:(N-S)/binary-unit:1>>))].
+
+test5(suite) -> [];
+test5(doc) -> ["OTP-3995"];
+test5(Config) when list(Config) ->
+ ?line test5(0, 8, <<73>>),
+ ?line test5(0, 8, <<68>>).
+
+test5(End, End, _) ->
+ ok;
+test5(I, End, A) ->
+ test5(I, A),
+ test5(I+1, End, A).
+
+test5(S, A) ->
+ N = 8,
+ Vars = [{'A', A}, {'N', 8}, {'S', S}],
+ lists:foreach(fun one_test/1, eval_list(gen_b(N, S, A), Vars)).
+
+%%% Failure cases
+testf(suite) -> [];
+testf(Config) when list(Config) ->
+ ?FAIL(<<3.14>>),
+ ?FAIL(<<<<1,2>>>>),
+
+ ?FAIL(<<2.71/binary>>),
+ ?FAIL(<<24334/binary>>),
+ ?FAIL(<<24334344294788947129487129487219847/binary>>),
+
+ ?FAIL(<<<<1,2,3>>/float>>),
+
+ %% Negative field widths.
+ testf_1(-8, <<1,2,3,4,5>>),
+
+ ?FAIL(<<42:(-16)>>),
+ ?FAIL(<<3.14:(-8)/float>>),
+ ?FAIL(<<<<23,56,0,2>>:(-16)/binary>>),
+ ?FAIL(<<<<23,56,0,2>>:(2.5)/binary>>),
+ ?FAIL(<<<<23,56,0,2>>:(anka)>>),
+
+ ok.
+
+testf_1(W, B) ->
+ ?FAIL(<<42:W>>),
+ ?FAIL(<<3.14:W/float>>),
+ ?FAIL(<<B:W/binary>>).
+
+not_used(doc) ->
+ "Test that constructed binaries that are not used will still give an exception.";
+not_used(Config) when is_list(Config) ->
+ ?line ok = not_used1(3, <<"dum">>),
+ ?line ?FAIL(not_used1(3, "dum")),
+ ?line ?FAIL(not_used2(444, -2)),
+ ?line ?FAIL(not_used2(444, anka)),
+ ?line ?FAIL(not_used3(444)),
+ ok.
+
+not_used1(I, BinString) ->
+ <<I:32,BinString/binary>>,
+ ok.
+
+not_used2(I, Sz) ->
+ <<I:Sz>>,
+ ok.
+
+not_used3(I) ->
+ <<I:(-8)>>,
+ ok.
+
+in_guard(Config) when list(Config) ->
+ ?line 1 = in_guard(<<16#74ad:16>>, 16#e95, 5),
+ ?line 2 = in_guard(<<16#3A,16#F7,"hello">>, 16#3AF7, <<"hello">>),
+ ?line 3 = in_guard(<<16#FBCD:14,3.1415/float,3:2>>, 16#FBCD, 3.1415),
+ nope = in_guard(<<1>>, 42, b),
+ nope = in_guard(<<1>>, a, b),
+ nope = in_guard(<<1,2>>, 1, 1),
+ nope = in_guard(<<4,5>>, 1, 2.71),
+ nope = in_guard(<<4,5>>, 1, <<12,13>>),
+ ok.
+
+in_guard(Bin, A, B) when <<A:13,B:3>> == Bin -> 1;
+in_guard(Bin, A, B) when <<A:16,B/binary>> == Bin -> 2;
+in_guard(Bin, A, B) when <<A:14,B/float,3:2>> == Bin -> 3;
+in_guard(Bin, A, B) when {a,b,<<A:14,B/float,3:2>>} == Bin -> cant_happen;
+in_guard(_, _, _) -> nope.
+
+-define(COF(Int0),
+ ?line (fun(Int) ->
+ true = <<Int:32/float>> =:= <<(float(Int)):32/float>>,
+ true = <<Int:64/float>> =:= <<(float(Int)):64/float>>
+ end)(nonliteral(Int0)),
+ ?line true = <<Int0:32/float>> =:= <<(float(Int0)):32/float>>,
+ ?line true = <<Int0:64/float>> =:= <<(float(Int0)):64/float>>).
+
+-define(COF64(Int0),
+ ?line (fun(Int) ->
+ true = <<Int:64/float>> =:= <<(float(Int)):64/float>>
+ end)(nonliteral(Int0)),
+ ?line true = <<Int0:64/float>> =:= <<(float(Int0)):64/float>>).
+
+nonliteral(X) -> X.
+
+coerce_to_float(Config) when list(Config) ->
+ ?COF(0),
+ ?COF(-1),
+ ?COF(1),
+ ?COF(42),
+ ?COF(255),
+ ?COF(-255),
+ ?COF(38474),
+ ?COF(387498738948729893849444444443),
+ ?COF(-37489378937773899999999999999993),
+ ?COF64(298748888888888888888888888883478264866528467367364766666666666666663),
+ ?COF64(-367546729879999999999947826486652846736736476555566666663),
+ ok.
diff --git a/lib/debugger/test/bs_match_bin_SUITE.erl b/lib/debugger/test/bs_match_bin_SUITE.erl
new file mode 100644
index 0000000000..3966dc41ef
--- /dev/null
+++ b/lib/debugger/test/bs_match_bin_SUITE.erl
@@ -0,0 +1,114 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2000-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+
+-module(bs_match_bin_SUITE).
+
+-author('[email protected]').
+-export([all/1,init_per_testcase/2,fin_per_testcase/2,init_all/1,finish_all/1,
+ byte_split_binary/1,bit_split_binary/1]).
+
+-include("test_server.hrl").
+
+all(suite) ->
+ [{conf,init_all,cases(),finish_all}].
+
+cases() ->
+ [byte_split_binary,bit_split_binary].
+
+init_per_testcase(_Case, Config) ->
+ test_lib:interpret(?MODULE),
+ Dog = test_server:timetrap(?t:minutes(1)),
+ [{watchdog,Dog}|Config].
+
+fin_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+init_all(Config) when is_list(Config) ->
+ ?line test_lib:interpret(?MODULE),
+ ?line true = lists:member(?MODULE, int:interpreted()),
+ ok.
+
+finish_all(Config) when is_list(Config) ->
+ ok.
+
+byte_split_binary(doc) -> "Tries to split a binary at all byte-aligned positions.";
+byte_split_binary(suite) -> [];
+byte_split_binary(Config) when list(Config) ->
+ ?line L = lists:seq(0, 57),
+ ?line B = mkbin(L),
+ ?line byte_split(L, B, size(B)).
+
+byte_split(L, B, Pos) when Pos >= 0 ->
+ ?line Sz1 = Pos,
+ ?line Sz2 = size(B) - Pos,
+ ?line <<B1:Sz1/binary,B2:Sz2/binary>> = B,
+ ?line B1 = list_to_binary(lists:sublist(L, 1, Pos)),
+ ?line B2 = list_to_binary(lists:nthtail(Pos, L)),
+ ?line byte_split(L, B, Pos-1);
+byte_split(_L, _B, _) -> ok.
+
+bit_split_binary(doc) -> "Tries to split a binary at all positions.";
+bit_split_binary(suite) -> [];
+bit_split_binary(Config) when list(Config) ->
+ Fun = fun(Bin, List, SkipBef, N) ->
+ ?line SkipAft = 8*size(Bin) - N - SkipBef,
+ io:format("~p, ~p, ~p", [SkipBef,N,SkipAft]),
+ ?line <<_I1:SkipBef,OutBin:N/binary-unit:1,_I2:SkipAft>> = Bin,
+ ?line OutBin = make_bin_from_list(List, N)
+ end,
+ ?line bit_split_binary1(Fun, erlang:md5(<<1,2,3>>)),
+ ok.
+
+bit_split_binary1(Action, Bin) ->
+ BitList = bits_to_list(binary_to_list(Bin), 16#80),
+ bit_split_binary2(Action, Bin, BitList, 0).
+
+bit_split_binary2(Action, Bin, [_|T]=List, Bef) ->
+ bit_split_binary3(Action, Bin, List, Bef, size(Bin)*8),
+ bit_split_binary2(Action, Bin, T, Bef+1);
+bit_split_binary2(_Action, _Bin, [], _Bef) -> ok.
+
+bit_split_binary3(Action, Bin, List, Bef, Aft) when Bef =< Aft ->
+ Action(Bin, List, Bef, (Aft-Bef) div 8 * 8),
+ bit_split_binary3(Action, Bin, List, Bef, Aft-8);
+bit_split_binary3(_, _, _, _, _) -> ok.
+
+make_bin_from_list(_List, 0) ->
+ mkbin([]);
+make_bin_from_list(List, N) ->
+ list_to_binary([make_int(List, 8, 0),
+ make_bin_from_list(lists:nthtail(8, List), N-8)]).
+
+
+make_int(_List, 0, Acc) -> Acc;
+make_int([H|T], N, Acc) -> make_int(T, N-1, Acc bsl 1 bor H).
+
+bits_to_list([_H|T], 0) -> bits_to_list(T, 16#80);
+bits_to_list([H|_]=List, Mask) ->
+ [case H band Mask of
+ 0 -> 0;
+ _ -> 1
+ end|bits_to_list(List, Mask bsr 1)];
+bits_to_list([], _) -> [].
+
+
+mkbin(L) when list(L) -> list_to_binary(L).
diff --git a/lib/debugger/test/bs_match_int_SUITE.erl b/lib/debugger/test/bs_match_int_SUITE.erl
new file mode 100644
index 0000000000..1159ac9ef8
--- /dev/null
+++ b/lib/debugger/test/bs_match_int_SUITE.erl
@@ -0,0 +1,230 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2000-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(bs_match_int_SUITE).
+
+-author('[email protected]').
+-export([all/1,init_per_testcase/2,fin_per_testcase/2,init_all/1,finish_all/1,
+ integer/1,signed_integer/1,dynamic/1,more_dynamic/1,mml/1]).
+
+-include("test_server.hrl").
+
+-import(lists, [seq/2]).
+
+all(suite) ->
+ [{conf,init_all,cases(),finish_all}].
+
+cases() ->
+ [integer,signed_integer,dynamic,more_dynamic,mml].
+
+init_per_testcase(_Case, Config) ->
+ test_lib:interpret(?MODULE),
+ Dog = test_server:timetrap(?t:minutes(4)),
+ [{watchdog,Dog}|Config].
+
+fin_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+init_all(Config) when is_list(Config) ->
+ ?line test_lib:interpret(?MODULE),
+ ?line true = lists:member(?MODULE, int:interpreted()),
+ ok.
+
+finish_all(Config) when is_list(Config) ->
+ ok.
+
+integer(suite) -> [];
+integer(Config) when list(Config) ->
+ ?line 0 = get_int(mkbin([])),
+ ?line 0 = get_int(mkbin([0])),
+ ?line 42 = get_int(mkbin([42])),
+ ?line 255 = get_int(mkbin([255])),
+ ?line 256 = get_int(mkbin([1,0])),
+ ?line 257 = get_int(mkbin([1,1])),
+ ?line 258 = get_int(mkbin([1,2])),
+ ?line 258 = get_int(mkbin([1,2])),
+ ?line 65534 = get_int(mkbin([255,254])),
+ ?line 16776455 = get_int(mkbin([255,253,7])),
+ ?line 4245492555 = get_int(mkbin([253,13,19,75])),
+ ?line Eight = [200,1,19,128,222,42,97,111],
+ ?line cmp128(Eight, uint(Eight)),
+ ?line fun_clause(catch get_int(mkbin(seq(1,5)))),
+ ok.
+
+get_int(<<I:0>>) -> I;
+get_int(<<I:8>>) -> I;
+get_int(<<I:16>>) -> I;
+get_int(<<I:24>>) -> I;
+get_int(<<I:32>>) -> I.
+
+cmp128(<<I:128>>, I) -> equal;
+cmp128(_B, _I) -> not_equal.
+
+signed_integer(suite) -> [];
+signed_integer(Config) when list(Config) ->
+ ?line {no_match,_} = sint(mkbin([])),
+ ?line {no_match,_} = sint(mkbin([1,2,3])),
+ ?line 127 = sint(mkbin([127])),
+ ?line -1 = sint(mkbin([255])),
+ ?line -128 = sint(mkbin([128])),
+ ?line 42 = sint(mkbin([42,255])),
+ ?line 127 = sint(mkbin([127,255])).
+
+sint(Bin) ->
+ case Bin of
+ <<I:8/signed>> -> I;
+ <<I:8/signed,_:3,_:5>> -> I;
+ Other -> {no_match,Other}
+ end.
+
+uint(L) -> uint(L, 0).
+uint([H|T], Acc) -> uint(T, Acc bsl 8 bor H);
+uint([], Acc) -> Acc.
+
+dynamic(Config) when list(Config) ->
+ dynamic(mkbin([255]), 8),
+ dynamic(mkbin([255,255]), 16),
+ dynamic(mkbin([255,255,255]), 24),
+ dynamic(mkbin([255,255,255,255]), 32),
+ ok.
+
+dynamic(Bin, S1) when S1 >= 0 ->
+ S2 = size(Bin) * 8 - S1,
+ dynamic(Bin, S1, S2, (1 bsl S1) - 1, (1 bsl S2) - 1),
+ dynamic(Bin, S1-1);
+dynamic(_Bin, _) -> ok.
+
+dynamic(Bin, S1, S2, A, B) ->
+% io:format("~p ~p ~p ~p\n", [S1,S2,A,B]),
+ case Bin of
+ <<A:S1,B:S2>> ->
+ io:format("~p ~p ~p ~p\n", [S1,S2,A,B]),
+ ok;
+ _Other ->
+ erlang:error(badmatch, [Bin,S1,S2,A,B])
+ end.
+
+more_dynamic(doc) -> "Extract integers at different alignments and of different sizes.";
+more_dynamic(Config) when list(Config) ->
+
+ % Unsigned big-endian numbers.
+ Unsigned = fun(Bin, List, SkipBef, N) ->
+ SkipAft = 8*size(Bin) - N - SkipBef,
+ <<_I1:SkipBef,Int:N,_I2:SkipAft>> = Bin,
+ Int = make_int(List, N, 0)
+ end,
+ ?line more_dynamic1(Unsigned, funny_binary(42)),
+
+ % Signed big-endian numbers.
+ Signed = fun(Bin, List, SkipBef, N) ->
+ SkipAft = 8*size(Bin) - N - SkipBef,
+ <<_I1:SkipBef,Int:N/signed,_I2:SkipAft>> = Bin,
+ case make_signed_int(List, N) of
+ Int -> ok;
+ Other ->
+ io:format("Bin = ~p,", [Bin]),
+ io:format("SkipBef = ~p, N = ~p", [SkipBef,N]),
+ io:format("Expected ~p, got ~p", [Int,Other]),
+ ?t:fail()
+ end
+ end,
+ ?line more_dynamic1(Signed, funny_binary(43)),
+
+ % Unsigned little-endian numbers.
+ UnsLittle = fun(Bin, List, SkipBef, N) ->
+ SkipAft = 8*size(Bin) - N - SkipBef,
+ <<_I1:SkipBef,Int:N/little,_I2:SkipAft>> = Bin,
+ Int = make_int(big_to_little(List, N), N, 0)
+ end,
+ ?line more_dynamic1(UnsLittle, funny_binary(44)),
+
+ % Signed little-endian numbers.
+ SignLittle = fun(Bin, List, SkipBef, N) ->
+ SkipAft = 8*size(Bin) - N - SkipBef,
+ <<_I1:SkipBef,Int:N/signed-little,_I2:SkipAft>> = Bin,
+ Little = big_to_little(List, N),
+ Int = make_signed_int(Little, N)
+ end,
+ ?line more_dynamic1(SignLittle, funny_binary(45)),
+
+ ok.
+
+funny_binary(N) ->
+ B0 = erlang:md5([N]),
+ {B1,_B2} = split_binary(B0, size(B0) div 2),
+ B1.
+
+more_dynamic1(Action, Bin) ->
+ BitList = bits_to_list(binary_to_list(Bin), 16#80),
+ more_dynamic2(Action, Bin, BitList, 0).
+
+more_dynamic2(Action, Bin, [_|T]=List, Bef) ->
+ more_dynamic3(Action, Bin, List, Bef, size(Bin)*8),
+ more_dynamic2(Action, Bin, T, Bef+1);
+more_dynamic2(_Action, _Bin, [], _Bef) -> ok.
+
+more_dynamic3(Action, Bin, List, Bef, Aft) when Bef =< Aft ->
+%% io:format("~p, ~p", [Bef,Aft-Bef]),
+ Action(Bin, List, Bef, Aft-Bef),
+ more_dynamic3(Action, Bin, List, Bef, Aft-1);
+more_dynamic3(_, _, _, _, _) -> ok.
+
+big_to_little(List, N) -> big_to_little(List, N, []).
+
+big_to_little([B0,B1,B2,B3,B4,B5,B6,B7|T], N, Acc) when N >= 8 ->
+ big_to_little(T, N-8, [B0,B1,B2,B3,B4,B5,B6,B7|Acc]);
+big_to_little(List, N, Acc) -> lists:sublist(List, 1, N) ++ Acc.
+
+make_signed_int(_List, 0) -> 0;
+make_signed_int([0|_T]=List, N) -> make_int(List, N, 0);
+make_signed_int([1|_T]=List0, N) ->
+ List1 = reversed_sublist(List0, N, []),
+ List2 = two_complement_and_reverse(List1, 1, []),
+ -make_int(List2, length(List2), 0).
+
+reversed_sublist(_List, 0, Acc) -> Acc;
+reversed_sublist([H|T], N, Acc) -> reversed_sublist(T, N-1, [H|Acc]).
+
+two_complement_and_reverse([H|T], Carry, Acc) ->
+ Sum = 1-H+Carry,
+ two_complement_and_reverse(T, Sum div 2, [Sum rem 2|Acc]);
+two_complement_and_reverse([], Carry, Acc) -> [Carry|Acc].
+
+make_int(_List, 0, Acc) -> Acc;
+make_int([H|T], N, Acc) -> make_int(T, N-1, Acc bsl 1 bor H).
+
+bits_to_list([_H|T], 0) -> bits_to_list(T, 16#80);
+bits_to_list([H|_]=List, Mask) ->
+ [case H band Mask of
+ 0 -> 0;
+ _ -> 1
+ end|bits_to_list(List, Mask bsr 1)];
+bits_to_list([], _) -> [].
+
+fun_clause({'EXIT',{function_clause,_}}) -> ok.
+mkbin(L) when list(L) -> list_to_binary(L).
+
+mml(Config) when list(Config) ->
+ ?line single_byte_binary = mml_choose(<<42>>),
+ ?line multi_byte_binary = mml_choose(<<42,43>>).
+
+mml_choose(<<_A:8>>) -> single_byte_binary;
+mml_choose(<<_A:8, _T/binary>>) -> multi_byte_binary.
diff --git a/lib/debugger/test/bs_match_misc_SUITE.erl b/lib/debugger/test/bs_match_misc_SUITE.erl
new file mode 100644
index 0000000000..5e1160a8e9
--- /dev/null
+++ b/lib/debugger/test/bs_match_misc_SUITE.erl
@@ -0,0 +1,152 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2000-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(bs_match_misc_SUITE).
+
+-author('[email protected]').
+-export([all/1,init_per_testcase/2,fin_per_testcase/2,init_all/1,finish_all/1,
+ bound_var/1,bound_tail/1,t_float/1,little_float/1,sean/1]).
+
+-include("test_server.hrl").
+
+all(suite) ->
+ [{conf,init_all,cases(),finish_all}].
+
+cases() ->
+ [bound_var,bound_tail,t_float,little_float,sean].
+
+init_per_testcase(_Case, Config) ->
+ test_lib:interpret(?MODULE),
+ Dog = test_server:timetrap(?t:minutes(1)),
+ [{watchdog,Dog}|Config].
+
+fin_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+init_all(Config) when is_list(Config) ->
+ ?line test_lib:interpret(?MODULE),
+ ?line true = lists:member(?MODULE, int:interpreted()),
+ ok.
+
+finish_all(Config) when is_list(Config) ->
+ ok.
+
+bound_var(doc) -> "Test matching of bound variables.";
+bound_var(Config) when list(Config) ->
+ ?line ok = bound_var(42, 13, <<42,13>>),
+ ?line nope = bound_var(42, 13, <<42,255>>),
+ ?line nope = bound_var(42, 13, <<154,255>>),
+ ok.
+
+bound_var(A, B, <<A:8,B:8>>) -> ok;
+bound_var(_, _, _) -> nope.
+
+bound_tail(doc) -> "Test matching of a bound tail.";
+bound_tail(Config) when list(Config) ->
+ ?line ok = bound_tail(<<>>, <<13,14>>),
+ ?line ok = bound_tail(<<2,3>>, <<1,1,2,3>>),
+ ?line nope = bound_tail(<<2,3>>, <<1,1,2,7>>),
+ ?line nope = bound_tail(<<2,3>>, <<1,1,2,3,4>>),
+ ?line nope = bound_tail(<<2,3>>, <<>>),
+ ok.
+
+bound_tail(T, <<_:16,T/binary>>) -> ok;
+bound_tail(_, _) -> nope.
+
+t_float(Config) when list(Config) ->
+ F = f1(),
+ G = f_one(),
+
+ ?line G = match_float(<<63,128,0,0>>, 32, 0),
+ ?line G = match_float(<<63,240,0,0,0,0,0,0>>, 64, 0),
+
+ ?line fcmp(F, match_float(<<F:32/float>>, 32, 0)),
+ ?line fcmp(F, match_float(<<F:64/float>>, 64, 0)),
+ ?line fcmp(F, match_float(<<1:1,F:32/float,127:7>>, 32, 1)),
+ ?line fcmp(F, match_float(<<1:1,F:64/float,127:7>>, 64, 1)),
+ ?line fcmp(F, match_float(<<1:13,F:32/float,127:3>>, 32, 13)),
+ ?line fcmp(F, match_float(<<1:13,F:64/float,127:3>>, 64, 13)),
+ ok.
+
+
+fcmp(F1, F2) when (F1 - F2) / F2 < 0.0000001 -> ok.
+
+match_float(Bin0, Fsz, I) ->
+ Bin = make_sub_bin(Bin0),
+ Bsz = size(Bin) * 8,
+ Tsz = Bsz - Fsz - I,
+ <<_:I,F:Fsz/float,_:Tsz>> = Bin,
+ F.
+
+little_float(Config) when list(Config) ->
+ F = f2(),
+ G = f_one(),
+
+ ?line G = match_float_little(<<0,0,0,0,0,0,240,63>>, 64, 0),
+ ?line G = match_float_little(<<0,0,128,63>>, 32, 0),
+
+ ?line fcmp(F, match_float_little(<<F:32/float-little>>, 32, 0)),
+ ?line fcmp(F, match_float_little(<<F:64/float-little>>, 64, 0)),
+ ?line fcmp(F, match_float_little(<<1:1,F:32/float-little,127:7>>, 32, 1)),
+ ?line fcmp(F, match_float_little(<<1:1,F:64/float-little,127:7>>, 64, 1)),
+ ?line fcmp(F, match_float_little(<<1:13,F:32/float-little,127:3>>, 32, 13)),
+ ?line fcmp(F, match_float_little(<<1:13,F:64/float-little,127:3>>, 64, 13)),
+
+ ok.
+
+match_float_little(Bin0, Fsz, I) ->
+ Bin = make_sub_bin(Bin0),
+ Bsz = size(Bin) * 8,
+ Tsz = Bsz - Fsz - I,
+ <<_:I,F:Fsz/float-little,_:Tsz>> = Bin,
+ F.
+
+
+make_sub_bin(Bin0) ->
+ Sz = size(Bin0),
+ Bin1 = <<37,Bin0/binary,38,39>>,
+ <<_:8,Bin:Sz/binary,_:8,_:8>> = Bin1,
+ Bin.
+
+f1() ->
+ 3.1415.
+
+f2() ->
+ 2.7133.
+
+f_one() ->
+ 1.0.
+
+sean(Config) when list(Config) ->
+ ?line small = sean1(<<>>),
+ ?line small = sean1(<<1>>),
+ ?line small = sean1(<<1,2>>),
+ ?line small = sean1(<<1,2,3>>),
+ ?line large = sean1(<<1,2,3,4>>),
+
+ ?line small = sean1(<<4>>),
+ ?line small = sean1(<<4,5>>),
+ ?line small = sean1(<<4,5,6>>),
+ ?line {'EXIT',{function_clause,_}} = (catch sean1(<<4,5,6,7>>)),
+ ok.
+
+sean1(<<B/binary>>) when size(B) < 4 -> small;
+sean1(<<1, _B/binary>>) -> large.
diff --git a/lib/debugger/test/bs_match_tail_SUITE.erl b/lib/debugger/test/bs_match_tail_SUITE.erl
new file mode 100644
index 0000000000..7fa16b3c6a
--- /dev/null
+++ b/lib/debugger/test/bs_match_tail_SUITE.erl
@@ -0,0 +1,106 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2000-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(bs_match_tail_SUITE).
+
+-author('[email protected]').
+-export([all/1,init_per_testcase/2,fin_per_testcase/2,init_all/1,finish_all/1,
+ aligned/1,unaligned/1,zero_tail/1]).
+
+-include("test_server.hrl").
+
+all(suite) ->
+ [{conf,init_all,cases(),finish_all}].
+
+cases() ->
+ [aligned,unaligned,zero_tail].
+
+init_per_testcase(_Case, Config) ->
+ test_lib:interpret(?MODULE),
+ Dog = test_server:timetrap(?t:minutes(1)),
+ [{watchdog,Dog}|Config].
+
+fin_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+init_all(Config) when is_list(Config) ->
+ ?line test_lib:interpret(?MODULE),
+ ?line true = lists:member(?MODULE, int:interpreted()),
+ ok.
+
+finish_all(Config) when is_list(Config) ->
+ ok.
+
+aligned(doc) -> "Test aligned tails.";
+aligned(Config) when list(Config) ->
+ ?line Tail1 = mkbin([]),
+ ?line {258,Tail1} = al_get_tail_used(mkbin([1,2])),
+ ?line Tail2 = mkbin(lists:seq(1, 127)),
+ ?line {35091,Tail2} = al_get_tail_used(mkbin([137,19|Tail2])),
+
+ ?line 64896 = al_get_tail_unused(mkbin([253,128])),
+ ?line 64895 = al_get_tail_unused(mkbin([253,127|lists:seq(42, 255)])),
+
+ ?line Tail3 = mkbin(lists:seq(0, 19)),
+ ?line {0,Tail1} = get_dyn_tail_used(Tail1, 0),
+ ?line {0,Tail3} = get_dyn_tail_used(mkbin([Tail3]), 0),
+ ?line {73,Tail3} = get_dyn_tail_used(mkbin([73|Tail3]), 8),
+
+ ?line 0 = get_dyn_tail_unused(mkbin([]), 0),
+ ?line 233 = get_dyn_tail_unused(mkbin([233]), 8),
+ ?line 23 = get_dyn_tail_unused(mkbin([23,22,2]), 8),
+ ok.
+
+al_get_tail_used(<<A:16,T/binary>>) -> {A,T}.
+al_get_tail_unused(<<A:16,_T/binary>>) -> A.
+
+unaligned(doc) -> "Test that an non-aligned tail cannot be matched out.";
+unaligned(Config) when list(Config) ->
+ ?line {'EXIT',{function_clause,_}} = (catch get_tail_used(mkbin([42]))),
+ ?line {'EXIT',{{badmatch,_},_}} = (catch get_dyn_tail_used(mkbin([137]), 3)),
+ ?line {'EXIT',{function_clause,_}} = (catch get_tail_unused(mkbin([42,33]))),
+ ?line {'EXIT',{{badmatch,_},_}} = (catch get_dyn_tail_unused(mkbin([44]), 7)),
+ ok.
+
+get_tail_used(<<A:1,T/binary>>) -> {A,T}.
+
+get_tail_unused(<<A:15,_/binary>>) -> A.
+
+get_dyn_tail_used(Bin, Sz) ->
+ <<A:Sz,T/binary>> = Bin,
+ {A,T}.
+
+get_dyn_tail_unused(Bin, Sz) ->
+ <<A:Sz,_T/binary>> = Bin,
+ A.
+
+zero_tail(doc) -> "Test that zero tails are tested correctly.";
+zero_tail(Config) when list(Config) ->
+ ?line 7 = (catch test_zero_tail(mkbin([7]))),
+ ?line {'EXIT',{function_clause,_}} = (catch test_zero_tail(mkbin([1,2]))),
+ ?line {'EXIT',{function_clause,_}} = (catch test_zero_tail2(mkbin([1,2,3]))),
+ ok.
+
+test_zero_tail(<<A:8>>) -> A.
+
+test_zero_tail2(<<_A:4,_B:4>>) -> ok.
+
+mkbin(L) when list(L) -> list_to_binary(L).
diff --git a/lib/debugger/test/bs_utf_SUITE.erl b/lib/debugger/test/bs_utf_SUITE.erl
new file mode 100644
index 0000000000..3d69d2a101
--- /dev/null
+++ b/lib/debugger/test/bs_utf_SUITE.erl
@@ -0,0 +1,292 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(bs_utf_SUITE).
+
+-export([all/1,init_all/1,finish_all/1,
+ init_per_testcase/2,fin_per_testcase/2,
+ utf8_roundtrip/1,unused_utf_char/1,utf16_roundtrip/1,
+ utf32_roundtrip/1,guard/1,extreme_tripping/1]).
+
+-include("test_server.hrl").
+-compile([no_jopt,time]).
+
+all(suite) ->
+ [{conf,init_all,cases(),finish_all}].
+
+cases() ->
+ [utf8_roundtrip,unused_utf_char,utf16_roundtrip,
+ utf32_roundtrip,guard,extreme_tripping].
+
+init_per_testcase(_Case, Config) ->
+ test_lib:interpret(?MODULE),
+ Dog = test_server:timetrap(?t:minutes(1)),
+ [{watchdog,Dog}|Config].
+
+fin_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+init_all(Config) when is_list(Config) ->
+ ?line test_lib:interpret(?MODULE),
+ ?line true = lists:member(?MODULE, int:interpreted()),
+ ok.
+
+finish_all(Config) when is_list(Config) ->
+ ok.
+
+utf8_roundtrip(Config) when is_list(Config) ->
+ ?line [utf8_roundtrip_1(P) || P <- utf_data()],
+ ok.
+
+utf8_roundtrip_1({Str,Bin,Bin}) ->
+ ?line Str = utf8_to_list(Bin),
+ ?line Bin = list_to_utf8(Str),
+ ?line [ok = utf8_guard(C, <<42,C/utf8>>) || C <- Str],
+ ?line [error = utf8_guard(C, <<C/utf8>>) || C <- Str],
+ ok.
+
+utf8_guard(C, Bin) when <<42,C/utf8>> =:= Bin -> ok;
+utf8_guard(_, _) -> error.
+
+utf8_to_list(<<C/utf8,T/binary>>) ->
+ [C|utf8_to_list(T)];
+utf8_to_list(<<>>) -> [].
+
+list_to_utf8(L) ->
+ list_to_utf8(L, <<>>).
+
+list_to_utf8([H|T], Bin) ->
+ list_to_utf8(T, <<Bin/binary,H/utf8>>);
+list_to_utf8([], Bin) -> Bin.
+
+unused_utf_char(Config) when is_list(Config) ->
+ [true = utf8_len(Utf8) =:= length(Str) ||
+ {Str,Utf8} <- utf_data()],
+ ok.
+
+utf8_len(B) ->
+ utf8_len(B, 0).
+
+utf8_len(<<_/utf8,T/binary>>, N) ->
+ utf8_len(T, N+1);
+utf8_len(<<>>, N) -> N.
+
+utf16_roundtrip(Config) when is_list(Config) ->
+ ?line {Str,Big,Big,Little,Little} = utf16_data(),
+ ?line 4 = utf16_big_len(Big),
+ ?line 4 = utf16_little_len(Little),
+ ?line Str = big_utf16_to_list(Big),
+ ?line Str = little_utf16_to_list(Little),
+
+ ?line Big = list_to_big_utf16(Str),
+ ?line Little = list_to_little_utf16(Str),
+
+ ok.
+
+utf16_big_len(B) ->
+ utf16_big_len(B, 0).
+
+utf16_big_len(<<_/utf16,T/binary>>, N) ->
+ utf16_big_len(T, N+1);
+utf16_big_len(<<>>, N) -> N.
+
+utf16_little_len(B) ->
+ utf16_little_len(B, 0).
+
+utf16_little_len(<<_/little-utf16,T/binary>>, N) ->
+ utf16_little_len(T, N+1);
+utf16_little_len(<<>>, N) -> N.
+
+list_to_big_utf16(List) ->
+ list_to_big_utf16(List, <<>>).
+
+list_to_big_utf16([H|T], Bin) ->
+ list_to_big_utf16(T, <<Bin/binary,H/utf16>>);
+list_to_big_utf16([], Bin) -> Bin.
+
+list_to_little_utf16(List) ->
+ list_to_little_utf16(List, <<>>).
+
+list_to_little_utf16([H|T], Bin) ->
+ list_to_little_utf16(T, <<Bin/binary,H/little-utf16>>);
+list_to_little_utf16([], Bin) -> Bin.
+
+big_utf16_to_list(<<H/utf16,T/binary>>) ->
+ [H|big_utf16_to_list(T)];
+big_utf16_to_list(<<>>) -> [].
+
+little_utf16_to_list(<<H/little-utf16,T/binary>>) ->
+ [H|little_utf16_to_list(T)];
+little_utf16_to_list(<<>>) -> [].
+
+utf32_roundtrip(Config) when is_list(Config) ->
+ ?line {Str,Big,Big,Little,Little} = utf32_data(),
+ ?line 4 = utf32_big_len(Big),
+ ?line 4 = utf32_little_len(Little),
+ ?line Str = big_utf32_to_list(Big),
+ ?line Str = little_utf32_to_list(Little),
+
+ ?line Big = list_to_big_utf32(Str),
+ ?line Little = list_to_little_utf32(Str),
+
+ ok.
+
+utf32_big_len(B) ->
+ utf32_big_len(B, 0).
+
+utf32_big_len(<<_/utf32,T/binary>>, N) ->
+ utf32_big_len(T, N+1);
+utf32_big_len(<<>>, N) -> N.
+
+utf32_little_len(B) ->
+ utf32_little_len(B, 0).
+
+utf32_little_len(<<_/little-utf32,T/binary>>, N) ->
+ utf32_little_len(T, N+1);
+utf32_little_len(<<>>, N) -> N.
+
+list_to_big_utf32(List) ->
+ list_to_big_utf32(List, <<>>).
+
+list_to_big_utf32([H|T], Bin) ->
+ list_to_big_utf32(T, <<Bin/binary,H/utf32>>);
+list_to_big_utf32([], Bin) -> Bin.
+
+list_to_little_utf32(List) ->
+ list_to_little_utf32(List, <<>>).
+
+list_to_little_utf32([H|T], Bin) ->
+ list_to_little_utf32(T, <<Bin/binary,H/little-utf32>>);
+list_to_little_utf32([], Bin) -> Bin.
+
+big_utf32_to_list(<<H/utf32,T/binary>>) ->
+ [H|big_utf32_to_list(T)];
+big_utf32_to_list(<<>>) -> [].
+
+little_utf32_to_list(<<H/little-utf32,T/binary>>) ->
+ [H|little_utf32_to_list(T)];
+little_utf32_to_list(<<>>) -> [].
+
+
+guard(Config) when is_list(Config) ->
+ ?line error = do_guard(16#D800),
+ ok.
+
+do_guard(C) when byte_size(<<C/utf8>>) =/= 42 -> ok;
+do_guard(C) when byte_size(<<C/utf16>>) =/= 42 -> ok;
+do_guard(C) when byte_size(<<C/utf32>>) =/= 42 -> ok;
+do_guard(_) -> error.
+
+%% The purpose of this test is to make sure that
+%% the delayed creation of sub-binaries works.
+
+extreme_tripping(Config) when is_list(Config) ->
+ ?line Unicode = lists:seq(0, 1024),
+ ?line Utf8 = unicode_to_utf8(Unicode, <<>>),
+ ?line Utf16 = utf8_to_utf16(Utf8, <<>>),
+ ?line Utf32 = utf8_to_utf32(Utf8, <<>>),
+ ?line Utf32 = utf16_to_utf32(Utf16, <<>>),
+ ?line Utf8 = utf32_to_utf8(Utf32, <<>>),
+ ?line Unicode = utf32_to_unicode(Utf32),
+ ok.
+
+unicode_to_utf8([C|T], Bin) ->
+ unicode_to_utf8(T, <<Bin/bytes,C/utf8>>);
+unicode_to_utf8([], Bin) -> Bin.
+
+utf8_to_utf16(<<C/utf8,T/binary>>, Bin) ->
+ utf8_to_utf16(T, <<Bin/bytes,C/utf16>>);
+utf8_to_utf16(<<>>, Bin) -> Bin.
+
+utf16_to_utf32(<<C/utf16,T/binary>>, Bin) ->
+ utf16_to_utf32(T, <<Bin/bytes,C/utf32>>);
+utf16_to_utf32(<<>>, Bin) -> Bin.
+
+utf8_to_utf32(<<C/utf8,T/binary>>, Bin) ->
+ utf8_to_utf32(T, <<Bin/bytes,C/utf32>>);
+utf8_to_utf32(<<>>, Bin) -> Bin.
+
+utf32_to_utf8(<<C/utf32,T/binary>>, Bin) ->
+ utf32_to_utf8(T, <<Bin/bytes,C/utf8>>);
+utf32_to_utf8(<<>>, Bin) -> Bin.
+
+utf32_to_unicode(<<C/utf32,T/binary>>) ->
+ [C|utf32_to_unicode(T)];
+utf32_to_unicode(<<>>) -> [].
+
+utf_data() ->
+%% From RFC-3629.
+
+ %% Give the compiler a change to do some constant propagation.
+ NotIdentical = 16#2262,
+
+ [
+ %% "A<NOT IDENTICAL TO><ALPHA>."
+ {[16#0041,NotIdentical,16#0391,16#002E],
+ <<16#0041/utf8,NotIdentical/utf8,16#0391/utf8,16#002E/utf8>>,
+ <<16#41,16#E2,16#89,16#A2,16#CE,16#91,16#2E>>},
+
+ %% Korean "hangugeo" (meaning "the Korean language")
+ {[16#D55C,16#AD6D,16#C5B4],
+ <<16#D55C/utf8,16#AD6D/utf8,16#C5B4/utf8>>,
+ <<16#ED,16#95,16#9C,16#EA,16#B5,16#AD,16#EC,16#96,16#B4>>},
+
+ %% Japanese "nihongo" (meaning "the Japanese language").
+ {[16#65E5,16#672C,16#8A9E],
+ <<16#65E5/utf8,16#672C/utf8,16#8A9E/utf8>>,
+ <<16#E6,16#97,16#A5,16#E6,16#9C,16#AC,16#E8,16#AA,16#9E>>}
+ ].
+
+utf16_data() ->
+ %% Example from RFC-2781. "*=Ra", where "*" represents a
+ %% hypothetical Ra hieroglyph (code point 16#12345).
+
+ %% Give the compiler a change to do some constant propagation.
+ RaHieroglyph = 16#12345,
+
+ %% First as a list of Unicode characters.
+ {[RaHieroglyph,16#3D,16#52,16#61],
+
+ %% Big endian (the two binaries should be equal).
+ <<RaHieroglyph/big-utf16,16#3D/big-utf16,16#52/big-utf16,16#61/big-utf16>>,
+ <<16#D8,16#08,16#DF,16#45,16#00,16#3D,16#00,16#52,16#00,16#61>>,
+
+ %% Little endian (the two binaries should be equal).
+ <<RaHieroglyph/little-utf16,16#3D/little-utf16,
+ 16#52/little-utf16,16#61/little-utf16>>,
+ <<16#08,16#D8,16#45,16#DF,16#3D,16#00,16#52,16#00,16#61,16#00>>}.
+
+utf32_data() ->
+ %% "A<NOT IDENTICAL TO><ALPHA>."
+ NotIdentical = 16#2262,
+ {[16#0041,NotIdentical,16#0391,16#002E],
+
+ %% Big endian.
+ <<16#0041/utf32,NotIdentical/utf32,16#0391/utf32,16#002E/utf32>>,
+ <<16#41:32,NotIdentical:32,16#0391:32,16#2E:32>>,
+
+ %% Little endian.
+ <<16#0041/little-utf32,NotIdentical/little-utf32,
+ 16#0391/little-utf32,16#002E/little-utf32>>,
+ <<16#41:32/little,NotIdentical:32/little,
+ 16#0391:32/little,16#2E:32/little>>}.
diff --git a/lib/debugger/test/bug_SUITE.erl b/lib/debugger/test/bug_SUITE.erl
new file mode 100644
index 0000000000..cf732c8115
--- /dev/null
+++ b/lib/debugger/test/bug_SUITE.erl
@@ -0,0 +1,79 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-module(bug_SUITE).
+
+-include("test_server.hrl").
+
+-export([all/1]).
+
+-export([ticket_tests/1]).
+
+-export([otp2163/1, otp4845/1]).
+
+all(suite) -> [ticket_tests].
+
+ticket_tests(doc) -> ["Tests tickets regarding bugs"];
+ticket_tests(suite) -> [otp2163, otp4845].
+
+otp2163(doc) -> ["BIF exit reason"];
+otp2163(suite) -> [];
+otp2163(Config) when list(Config) ->
+ ?line DataDir = ?config(data_dir, Config),
+
+ %% First compile and get the expected results:
+
+ ?line FileName = filename:join(DataDir, "otp2163"),
+ ?line {module,otp2163} = code:load_abs(FileName),
+
+ ?line {'EXIT',{badarg,[ApplyRes|_]}} = (catch otp2163:apply_test()),
+ ?line {'EXIT',{badarg,[ListRes|_]}} = (catch otp2163:list_to_atom_test()),
+
+ %% Then interpret, and check if the results are OK.
+ ?line {module,otp2163} = int:i(FileName),
+
+ ?line ok = io:format("Expecting ~p", [ApplyRes]),
+ ?line {'EXIT',{badarg,[ApplyRes|_]}} = (catch otp2163:apply_test()),
+ ?line ok = io:format("Expecting ~p", [ListRes]),
+ ?line {'EXIT',{badarg,[ListRes|_]}} = (catch otp2163:list_to_atom_test()),
+ ok.
+
+
+otp4845(doc) -> ["BIF not loading and not bug compatible, OTP-4845 OTP-4859"];
+otp4845(suite) -> [];
+otp4845(Config) when list(Config) ->
+ ?line DataDir = ?config(data_dir, Config),
+
+ %% First compile and get the expected results:
+
+ ?line FileName = filename:join(DataDir, "otp4845"),
+ ?line {module,otp4845} = code:load_abs(FileName),
+
+ ?line CompiledRes = (catch otp4845:test()),
+ ?line ok = io:format("Compiled ~p", [CompiledRes]),
+
+ %% Then interpret, and check if the results are OK.
+ ?line {module,otp4845} = int:i(FileName),
+
+ ?line IntRes = (catch otp4845:test()),
+ ?line ok = io:format("Interpreted ~p", [IntRes]),
+
+ ?line CompiledRes = IntRes,
+ ok.
diff --git a/lib/debugger/test/bug_SUITE_data/Makefile.src b/lib/debugger/test/bug_SUITE_data/Makefile.src
new file mode 100644
index 0000000000..792b3299e1
--- /dev/null
+++ b/lib/debugger/test/bug_SUITE_data/Makefile.src
@@ -0,0 +1,25 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2000-2010. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+all: otp2163.@EMULATOR@ otp4845.@EMULATOR@
+EFLAGS=+debug_info
+
+otp2163.@EMULATOR@: otp2163.erl
+ erlc $(EFLAGS) otp2163.erl
+otp4845.@EMULATOR@: otp4845.erl
+ erlc $(EFLAGS) otp4845.erl
diff --git a/lib/debugger/test/bug_SUITE_data/otp2163.erl b/lib/debugger/test/bug_SUITE_data/otp2163.erl
new file mode 100644
index 0000000000..4e3c487ef7
--- /dev/null
+++ b/lib/debugger/test/bug_SUITE_data/otp2163.erl
@@ -0,0 +1,60 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%% Purpose : Test OTP-2163
+
+-module(otp2163).
+
+
+-export([apply_test/0, list_to_atom_test/0, error/1]).
+-export([test/0]).
+
+apply_test() ->
+ M = {},
+ apply(M,dummy,[]).
+
+list_to_atom_test() ->
+ list_to_atom(id({1,2})).
+
+id(I) -> I.
+
+%% OTP-4845 OTP 4859
+-record(sune, {a,sd,g,s}).
+-record(error, {a,sd,g,s}).
+
+test() ->
+ sune = error(#sune{}),
+ {false,false} = error(false),
+ {true,true} = error(true),
+ error(#error{}).
+
+error(X) ->
+ if
+ is_record(X, sune) ->
+ sune;
+ X ->
+ {true, X};
+ not X ->
+ {false, X};
+ not is_record(X, error) ->
+ error;
+ true ->
+ ok
+ end.
diff --git a/lib/debugger/test/bug_SUITE_data/otp4845.erl b/lib/debugger/test/bug_SUITE_data/otp4845.erl
new file mode 100644
index 0000000000..18ca08b977
--- /dev/null
+++ b/lib/debugger/test/bug_SUITE_data/otp4845.erl
@@ -0,0 +1,52 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%% Purpose : Test OTP-4845
+
+-module(otp4845).
+
+
+%%-export([error/1]).
+-export([test/0]).
+
+%% OTP-4845 OTP 4859
+-record(sune, {a,sd,g,s}).
+-record(error, {a,sd,g,s}).
+
+test() ->
+ R1 = error(#sune{}),
+ R2 = error(false),
+ R3 = error(true),
+ R4 = error(#error{}),
+ {R1,R2,R3,R4}.
+
+error(X) ->
+ if
+ is_record(X, sune) ->
+ sune;
+ X ->
+ {true, X};
+ not X ->
+ {false, X};
+ not is_record(X, error) ->
+ error;
+ true ->
+ ok
+ end.
diff --git a/lib/debugger/test/cleanup.erl b/lib/debugger/test/cleanup.erl
new file mode 100644
index 0000000000..59b4c35ac7
--- /dev/null
+++ b/lib/debugger/test/cleanup.erl
@@ -0,0 +1,45 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-module(cleanup).
+
+-export([all/1, cleanup/1]).
+
+-include("test_server.hrl").
+
+all(suite) -> {req, [interpreter], [cleanup]}.
+
+cleanup(suite) -> [];
+cleanup(_) ->
+ ?line Mods = int:interpreted(),
+ ?line ok = int:n(Mods),
+ case whereis(interpret) of
+ undefined ->
+ ok;
+ Pid ->
+ exit(Pid, kill)
+ end,
+ case whereis(int_db) of
+ undefined ->
+ ok;
+ Pid2 ->
+ exit(Pid2, kill)
+ end,
+ ok.
diff --git a/lib/debugger/test/dbg_ui_SUITE.erl b/lib/debugger/test/dbg_ui_SUITE.erl
new file mode 100644
index 0000000000..629aac9fd6
--- /dev/null
+++ b/lib/debugger/test/dbg_ui_SUITE.erl
@@ -0,0 +1,288 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-module(dbg_ui_SUITE).
+
+
+-include("test_server.hrl").
+
+
+% Test server specific exports
+-export([all/1]).
+-export([function_tests/1]).
+
+
+% Test cases must be exported.
+-export ([dbg_ui/1]).
+
+
+
+
+
+% Manual test suites/cases exports
+-export([manual_tests/1]).
+-export([start1/1, interpret1/1, quit1/1,
+ start2/1, interpret2/1, break2/1, options2/1, quit2/1,
+ interpret3/1, all_step3/1,all_next3/1,save3/1,restore3/1,finish3/1,
+ killinit3/1, killone3/1, killall3/1, deleteone3/1, deleteall3/1,
+ viewbreak4/1, delete4/1,
+ attach5/1, normal5/1, exit5/1, options5/1,
+ distsetup6/1, all_step6/1, all_next6/1]).
+
+
+
+
+-export([init_per_testcase/2, fin_per_testcase/2]).
+
+
+
+init_per_testcase(_Func, Config) ->
+ Dog=test_server:timetrap(60*1000),
+ [{watchdog, Dog}|Config].
+
+fin_per_testcase(_Func, Config) ->
+ Dog=?config(watchdog, Config),
+ test_server:timetrap_cancel(Dog).
+
+
+all (suite)->
+ {req, [debugger], [function_tests, manual_tests]}.
+
+
+function_tests (doc) ->
+ ["Tests documented functions"];
+
+function_tests (suite) ->
+ [dbg_ui].
+
+
+
+dbg_ui (doc) ->
+ ["Debugger GUI"];
+
+dbg_ui (suite) ->
+ [];
+
+dbg_ui (_Config) ->
+ case os:getenv("DISPLAY") of
+ false ->
+ {skipped,"No display"};
+ Other when list(Other) ->
+% ?line {ok, Pid} = debugger:start (),
+% ?line ok = is_pid (Pid),
+% ?line true = erlang:is_process_alive(Pid),
+% ?line ok = debugger:stop(),
+% ?line false = erlang:is_process_alive(Pid)
+ {skipped,"Gunilla: Workaround"}
+ end.
+
+
+
+
+
+
+%% check/2 - returns the result for the specified testcase.
+%% pass - means the user has run the case, and it passed
+%% fail - means the user has run the case, and it failed
+%% unknown - means the user has (tried to) run the case, and the result is unclear.
+%% skip - means the user has not yet run the case.
+
+check(Case, Config) ->
+
+ ?line DataDir = ?config(data_dir, Config),
+ ?line ResultFileName = filename:join([DataDir, "manual_results.erl"]),
+ case file:consult(ResultFileName) of
+ {ok, Results} ->
+ ?line io:format("Results: ~p~n",[Results]),
+ case Results of
+ [] ->
+ no_result;
+ %% Incomplete "sanity" check of file contents.
+ [{_Key,_Value}|_Rest] ->
+ case lists:keysearch(Case, 1, Results) of
+ {value, {Case, Value}} ->
+ Value; % pass, fail, unknown
+ false ->
+ no_result; % skip
+ _Otherwise ->
+ {error, "Contents of results file not valid"}
+ end;
+ _Otherwise2 ->
+ {error, "Contents of results file not valid"}
+ end;
+ _Otherwise3 ->
+ {error, "Problems reading results file"}
+ end.
+
+
+
+
+
+
+-define(MAN_CASE(Name,Doc, Description),
+ Name(doc) -> [Doc];
+ Name(suite) -> [];
+ Name(Config) ->
+ ?line io:format("Checking ~p~n",[Name]),
+ ?line io:format("Config = ~p~n",[Config]),
+ case check(Name, Config) of
+ pass ->
+ ?line ok;
+ fail ->
+ ?line test_server:fail("Manual test failed");
+ unknown ->
+ ?line {skipped, "Manual test result unknown"};
+
+ no_result ->
+ ?line {skipped, Description};
+
+ {error, _Reason} ->
+%% Text = lists:flatten(
+%% io_lib:format("[File problem: ~s]~s",
+%% [Reason,Description])),
+ ?line {skipped, Description}
+ end
+ ).
+
+
+
+
+manual_tests(doc) -> ["Manual tests"];
+manual_tests(suite) -> [start1, interpret1, quit1,
+ start2, interpret2, break2, options2,
+ interpret3, all_step3,all_next3,save3,restore3,finish3,
+ killinit3, killone3, killall3, deleteone3, deleteall3,
+ viewbreak4, delete4,
+ attach5, normal5, exit5, options5,
+ distsetup6, all_step6, all_next6
+ ].
+
+
+
+
+
+
+%% SET 1
+?MAN_CASE(start1, "Start the debugger from the toolbar",
+ "Before proceeding with the test cases, please move or remove
+the directory .erlang_tools/debugger in your home directory. Next,
+please start the debugger from the toolbar").
+
+?MAN_CASE(interpret1, "Interpreting modules",
+ "In this test case and all of the ones following, the source code
+files to use can be found in the test data directory for this debugger test
+ suite (probably in
+/clearcase/otp/tools/debugger/test/dbg_ui_SUITE_data/manual_data/src ).
+Interpret one module").
+
+?MAN_CASE(quit1, "Quit the debugger",
+"Quit the debugger using File->Exit in the main window").
+
+
+%% SET 2
+?MAN_CASE(start2, "Start the debugger from the shell",
+"Start the debugger from the shell. Use debugger:start()").
+
+?MAN_CASE(interpret2, "Interpret all modules",
+"Interpret all modules").
+
+?MAN_CASE(break2, "Set break points",
+"Set break points").
+
+?MAN_CASE(options2, "Set options to attach on break",
+"Set options to attach on break").
+
+?MAN_CASE(quit2, "Quit the debugger",
+"Quit the debugger using the close box in the main window title frame").
+
+
+%% SET3
+?MAN_CASE(interpret3, "Test attach options",
+"Start the debugger and interpret the modules [test, lists1, ordsets1]. Close the Interpret dialog. Set Attach on First Call and Attach on Break.").
+
+?MAN_CASE(all_step3, "Click Step through all evaluation",
+"In the shell, call test:test1(). Use the Step button, the Process->Step menu item and the ctrl-s shortcut to step through the *entire* execution of the call. (Approx 36 steps). Then close the Attach window. The result printed in the shell should be: {\"peter\",[1,2,4,a,b,c],\"olin\"}").
+
+?MAN_CASE(all_next3,"Click Next through all evaluation",
+"Again call test:test1() in the shell. This time Use the Next button, the Process->Next menu and the ctrl-n shortcut to quickly step over the execution of the four lines in the test1-function. The result printed in the shell should be: {\"peter\",[1,2,4,a,b,c],\"olin\"}").
+
+?MAN_CASE(save3, "Save the debugger state",
+"Use File->Save Settings to save the debugger state with the name 'three.state'").
+
+?MAN_CASE(restore3,"Quit the debugger, restart and restore the state",
+"Quit the debugger. Start it again. Use File->Load Settings to restore the state saved in 'three.state'. Check that the Attach-options are the same as what you set them to in the interpret3 test case. Check that the three modules [test,lists1,ordsets1] are interpreted.").
+
+
+?MAN_CASE(finish3, "Finish the current function body",
+"Call the fucntion test:test1() from the shell. Press Finish to evaluate the remaining lines in the function. The result printed in the shell should be: {\"peter\",[1,2,4,a,b,c],\"olin\"}").
+
+?MAN_CASE(killinit3,"Set up for killing and clearing processes",
+"Call test:test2() from the shell. Set a break point at the last line of test:test2. Click Continue. This should open three new attach windows. One for each spawn called in test:test2/0. ").
+
+?MAN_CASE(killone3, "Kill a process and clear it",
+"In one of the newly openend Attach windows: select Process->Kill. A message should appear above the Code Area in the Attach window. Use Windows->Monitor to verify that the Monitor window also shows that the process has been killed. In the Monitor window: select Edit->Clear. This should do two things: 1) close/remove the window of the killed process. 2) Remove the entry of the killed process from the monitor window.").
+
+?MAN_CASE(killall3,"KIll all processes, and clear them",
+"In the Monitor window: Select Edit->Kill All. Verify that all processes have been killed (in their respective windows and in the monitor window). Windows will be raised as their processes die. Next select, Edit->Clear. All attach windows should now be closed. Their entris should also disappear from the monitor window. The shell should have reported: ** exited: killed **").
+
+?MAN_CASE(deleteone3,"Delete/uniterpret one module",
+"In the Monitor window: Select Module->test->Delete. This should remove the breakpoints set in the test module, and the test module should disappear from the Module menu.").
+
+?MAN_CASE(deleteall3,"Delete/uniterpret all modules",
+"In the Monitor window: Select Module->Delete All Modules. This should remove all modules from the Module menu. ").
+
+%% SET 4
+
+
+
+?MAN_CASE(viewbreak4, "Test the View window",
+"Restore the settings from the three.state file again. In the Monitor window: Use Module->test->View to view the source code of the test module. In the View window, select Break->Line Break and set a break at line 53. Check that it appears in the View window and in the Monitor Window Break-menu. Also in the View window, select Break->Function Break and set a break at function test:test4. Check that the break (at line 59) appears in the View Window and in the Monitor Window Break-menu.").
+
+?MAN_CASE(delete4, "Remove breaks",
+"Use the Break->Delete All function in the View window to remove all breaks in the test module. Check that they are all removed. Close the View window.").
+
+%% SET 5
+
+?MAN_CASE(attach5,"Set attach options",
+"Set the attach options to only attach on exit").
+
+?MAN_CASE(normal5, "Test normal exit",
+"Call test:test12(normal) in the shell. This should return the atom 'done', and no windows should be opened.").
+
+?MAN_CASE(exit5, "Test abnormal exit",
+"Call test:test12(crash) in the shell. This should give the error message ** exited: crash **, and an attach window should be opened highlighting the last line in the test12-function.").
+
+?MAN_CASE(options5, "Experiment with the frames in the attach window",
+"Try all possible configurations of the [Button, Evaluator, Bindings, Trace] Frames in the attach window and see that the expected frames are shown/hidden.").
+
+
+%% SET 6 (Distribution)
+
+?MAN_CASE(distsetup6,"Set up distribution",
+"Start two erlang systems [foo,bar] (with option -sname), make them aware of eachother using net_adm:ping/1. Start the debugger on foo. Interpret the modules [test, lists1, ordsets1]. Set attach on First call. ").
+
+
+
+
+?MAN_CASE(all_step6, "Click Step through all evaluation",
+"In the bar shell, call test:test1().This should open an attach window. Use the Step button, the Process->Step menu item and the ctrl-s shortcut to step through the *entire* execution of the call. (Approx 36 steps). Then close the Attach window. The result printed in the bar shell should be: {\"peter\",[1,2,4,a,b,c],\"olin\"}").
+
+?MAN_CASE(all_next6,"Click Next through all evaluation",
+"Again, in the bar shell, call test:test1(). This time Use the Next button, the Process->Next menu and the ctrl-n shortcut to quickly step over the execution of the four lines in the test1-function. The result printed in the shell should be: {\"peter\",[1,2,4,a,b,c],\"olin\"}").
diff --git a/lib/debugger/test/dbg_ui_SUITE_data/manual_data/src/lists1.erl b/lib/debugger/test/dbg_ui_SUITE_data/manual_data/src/lists1.erl
new file mode 100644
index 0000000000..0214983c11
--- /dev/null
+++ b/lib/debugger/test/dbg_ui_SUITE_data/manual_data/src/lists1.erl
@@ -0,0 +1,469 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Purpose : Basic lists processing functions.
+
+-module(lists1).
+
+
+-export([member/2, append/2, append/1, subtract/2, reverse/1, reverse/2,
+ nth/2, nthtail/2, prefix/2, suffix/2, last/1,
+ seq/2, seq/3, sum/1, duplicate/2, min/1, max/1, sublist/2, sublist/3,
+ delete/2, sort/1, merge/2, concat/1,
+ flatten/1, flatten/2, flat_length/1, flatlength/1,
+ keymember/3, keysearch/3, keydelete/3, keyreplace/4,
+ keysort/2, keymerge/3, keymap/3, keymap/4]).
+
+-export([all/2,any/2,map/2,flatmap/2,foldl/3,foldr/3,filter/2,zf/2,
+ mapfoldl/3,mapfoldr/3,foreach/2,takewhile/2,dropwhile/2,splitwith/2]).
+-export([all/3,any/3,map/3,flatmap/3,foldl/4,foldr/4,filter/3,zf/3,
+ mapfoldl/4,mapfoldr/4,foreach/3]).
+
+%% member(X, L) -> (true | false)
+%% test if X is a member of the list L
+
+member(X, [X|_]) -> true;
+member(X, [_|Y]) ->
+ member(X, Y);
+member(X, []) -> false.
+
+%% append(X, Y) appends lists X and Y
+
+append(L1, L2) -> L1 ++ L2.
+
+%% append(L) appends the list of lists L
+
+append([E]) -> E;
+append([H|T]) -> H ++ append(T);
+append([]) -> [].
+
+%% subtract(List1, List2) subtract elements in List2 form List1.
+
+subtract(L1, L2) -> L1 -- L2.
+
+%% reverse(L) reverse all elements in the list L
+
+reverse(X) -> reverse(X, []).
+
+reverse([H|T], Y) ->
+ reverse(T, [H|Y]);
+reverse([], X) -> X.
+
+%% nth(N, L) returns the N`th element of the list L
+%% nthtail(N, L) returns the N`th tail of the list L
+
+nth(1, [H|T]) -> H;
+nth(N, [_|T]) when N > 1 ->
+ nth(N - 1, T).
+
+nthtail(1, [H|T]) -> T;
+nthtail(N, [H|T]) when N > 1 ->
+ nthtail(N - 1, T);
+nthtail(0, L) when list(L) -> L.
+
+%% prefix(Prefix, List) -> (true | false)
+
+prefix([X|PreTail], [X|Tail]) ->
+ prefix(PreTail, Tail);
+prefix([], List) -> true;
+prefix(_,_) -> false.
+
+
+%% suffix(Suffix, List) -> (true | false)
+
+suffix(Suffix, Suffix) -> true;
+suffix(Suffix, [_|Tail]) ->
+ suffix(Suffix, Tail);
+suffix(Suffix, []) -> false.
+
+%% last(List) returns the last element in a list.
+
+last([E]) -> E;
+last([E|Es]) ->
+ last(Es).
+
+%% seq(Min, Max) -> [Min,Min+1, ..., Max]
+%% seq(Min, Max, Incr) -> [Min,Min+Incr, ..., Max]
+%% returns the sequence Min..Max
+%% Min <= Max and Min and Max must be integers
+
+seq(Min, Max) when integer(Min), integer(Max), Min =< Max ->
+ seq(Min, Max, 1, []).
+
+seq(Min, Max, Incr) ->
+ seq(Min, Min + ((Max-Min) div Incr) * Incr, Incr, []).
+
+seq(Min, Min, I, L) -> [Min|L];
+seq(Min, Max, I, L) -> seq(Min, Max-I, I, [Max|L]).
+
+%% sum(L) suns the sum of the elements in L
+
+sum(L) -> sum(L, 0).
+sum([H|T], Sum) -> sum(T, Sum + H);
+sum([], Sum) -> Sum.
+
+%% duplicate(N, X) -> [X,X,X,.....,X] (N times)
+%% return N copies of X
+
+duplicate(N, X) when integer(N), N >= 0 -> duplicate(N, X, []).
+
+duplicate(0, _, L) -> L;
+duplicate(N, X, L) -> duplicate(N-1, X, [X|L]).
+
+
+%% min(L) -> returns the minimum element of the list L
+
+min([H|T]) -> min(T, H).
+
+min([H|T], Min) when H < Min -> min(T, H);
+min([_|T], Min) -> min(T, Min);
+min([], Min) -> Min.
+
+%% max(L) -> returns the maximum element of the list L
+
+max([H|T]) -> max(T, H).
+
+max([H|T], Max) when H > Max -> max(T, H);
+max([_|T], Max) -> max(T, Max);
+max([], Max) -> Max.
+
+%% sublist(List, Start, Length)
+%% Returns the sub-list starting at Start of length Length.
+
+sublist(List, S, L) when L >= 0 ->
+ sublist(nthtail(S-1, List), L).
+
+sublist([H|T], L) when L > 0 ->
+ [H|sublist(T, L-1)];
+sublist(List, L) -> [].
+
+%% delete(Item, List) -> List'
+%% Delete the first occurance of Item from the list L.
+
+delete(Item, [Item|Rest]) -> Rest;
+delete(Item, [H|Rest]) ->
+ [H|delete(Item, Rest)];
+delete(Item, []) -> [].
+
+%% sort(L) -> sorts the list L
+
+sort([X]) -> [X];
+sort([]) -> [];
+sort(X) -> split_and_sort(X, [], []).
+
+split_and_sort([A,B|T], X, Y) ->
+ split_and_sort(T, [A|X], [B|Y]);
+split_and_sort([H], X, Y) ->
+ split_and_sort([], [H|X], Y);
+split_and_sort([], X, Y) ->
+ merge(sort(X), sort(Y), []).
+
+%% merge(X, Y) -> L
+%% merges two sorted lists X and Y
+
+merge(X, Y) -> merge(X, Y, []).
+
+merge([H1|T1], [H2|T2], L) when H1 < H2 ->
+ merge(T1, [H2|T2], [H1|L]);
+merge(T1, [H2|T2], L) ->
+ merge(T1, T2, [H2|L]);
+merge([H|T], T2, L) ->
+ merge(T, T2, [H|L]);
+merge([], [], L) ->
+ reverse(L).
+
+%% concat(L) concatinate the list representation of the elements
+%% in L - the elements in L can be atoms, integers of strings.
+%% Returns a list of characters.
+
+concat(List) ->
+ flatmap(fun thing_to_list/1, List).
+
+thing_to_list(X) when integer(X) -> integer_to_list(X);
+thing_to_list(X) when float(X) -> float_to_list(X);
+thing_to_list(X) when atom(X) -> atom_to_list(X);
+thing_to_list(X) when list(X) -> X. %Assumed to be a string
+
+%% flatten(List)
+%% flatten(List, Tail)
+%% Flatten a list, adding optional tail.
+
+flatten(List) ->
+ flatten(List, [], []).
+
+flatten(List, Tail) ->
+ flatten(List, [], Tail).
+
+flatten([H|T], Cont, Tail) when list(H) ->
+ flatten(H, [T|Cont], Tail);
+flatten([H|T], Cont, Tail) ->
+ [H|flatten(T, Cont, Tail)];
+flatten([], [H|Cont], Tail) ->
+ flatten(H, Cont, Tail);
+flatten([], [], Tail) ->
+ Tail.
+
+%% flat_length(List) (undocumented can be rmove later)
+%% Calculate the length of a list of lists.
+
+flat_length(List) -> flatlength(List).
+
+%% flatlength(List)
+%% Calculate the length of a list of lists.
+
+flatlength(List) ->
+ flatlength(List, 0).
+
+flatlength([H|T], L) when list(H) ->
+ flatlength(H, flatlength(T, L));
+flatlength([H|T], L) ->
+ flatlength(T, L + 1);
+flatlength([], L) -> L.
+
+%% keymember(Key, Index, [Tuple])
+%% keysearch(Key, Index, [Tuple])
+%% keydelete(Key, Index, [Tuple])
+%% keyreplace(Key, Index, [Tuple], NewTuple)
+%% keysort(Index, [Tuple])
+%% keymerge(Index, [Tuple], [Tuple])
+%% keymap(Function, Index, [Tuple])
+%% keymap(Function, ExtraArgs, Index, [Tuple])
+
+keymember(Key, N, [T|Ts]) when element(N, T) == Key -> true;
+keymember(Key, N, [T|Ts]) ->
+ keymember(Key, N, Ts);
+keymember(Key, N, []) -> false.
+
+keysearch(Key, N, [H|T]) when element(N, H) == Key ->
+ {value, H};
+keysearch(Key, N, [H|T]) ->
+ keysearch(Key, N, T);
+keysearch(Key, N, []) -> false.
+
+keydelete(Key, N, [H|T]) when element(N, H) == Key -> T;
+keydelete(Key, N, [H|T]) ->
+ [H|keydelete(Key, N, T)];
+keydelete(Key, N, []) -> [].
+
+keyreplace(Key, Pos, [Tup|Tail], New) when element(Pos, Tup) == Key ->
+ [New|Tail];
+keyreplace(Key, Pos, [H|T], New) ->
+ [H|keyreplace(Key, Pos, T, New)];
+keyreplace(Key, Pos, [], New) -> [].
+
+keysort(Index, [X]) -> [X];
+keysort(Index, []) -> [];
+keysort(Index, X) -> split_and_keysort(X, [], [], Index).
+
+split_and_keysort([A,B|T], X, Y, Index) ->
+ split_and_keysort(T, [A|X], [B|Y], Index);
+split_and_keysort([H], X, Y, Index) ->
+ split_and_keysort([], [H|X], Y, Index);
+split_and_keysort([], X, Y, Index) ->
+ keymerge(Index, keysort(Index, X), keysort(Index, Y), []).
+
+keymerge(Index, X, Y) -> keymerge(Index, X, Y, []).
+
+keymerge(I, [H1|T1], [H2|T2], L) when element(I, H1) < element(I, H2) ->
+ keymerge(I, T1, [H2|T2], [H1|L]);
+keymerge(Index, T1, [H2|T2], L) ->
+ keymerge(Index,T1, T2, [H2|L]);
+keymerge(Index,[H|T], T2, L) ->
+ keymerge(Index,T, T2, [H|L]);
+keymerge(Index, [], [], L) ->
+ reverse(L).
+
+keymap(Fun, Index, [Tup|Tail]) ->
+ [setelement(Index, Tup, Fun(element(Index, Tup)))|keymap(Fun, Index, Tail)];
+keymap( _, _ , []) -> [].
+
+keymap(Fun, ExtraArgs, Index, [Tup|Tail]) ->
+ [setelement(Index, Tup, apply(Fun, [element(Index, Tup)|ExtraArgs]))|
+ keymap(Fun, ExtraArgs, Index, Tail)];
+keymap( _, _ , _, []) -> [].
+
+%% all(Predicate, List)
+%% any(Predicate, List)
+%% map(Function, List)
+%% flatmap(Function, List)
+%% foldl(Function, First, List)
+%% foldr(Function, Last, List)
+%% filter(Predicate, List)
+%% zf(Function, List)
+%% mapfoldl(Function, First, List)
+%% mapfoldr(Function, Last, List)
+%% foreach(Function, List)
+%% takewhile(Predicate, List)
+%% dropwhile(Predicate, List)
+%% splitwith(Predicate, List)
+%% for list programming. Function here is either a 'fun' or a tuple
+%% {Module,Name} and we use apply/2 to evaluate. The name zf is a joke!
+%%
+%% N.B. Unless where the functions actually needs it only foreach/2/3,
+%% which is meant to be used for its side effects, has a defined order
+%% of evaluation.
+%%
+%% There are also versions with an extra argument, ExtraArgs, which is a
+%% list of extra arguments to each call.
+
+all(Pred, [Hd|Tail]) ->
+ case Pred(Hd) of
+ true -> all(Pred, Tail);
+ false -> false
+ end;
+all(Pred, []) -> true.
+
+any(Pred, [Hd|Tail]) ->
+ case Pred(Hd) of
+ true -> true;
+ false -> any(Pred, Tail)
+ end;
+any(Pred, []) -> false.
+
+map(F, List) -> [ F(E) || E <- List ].
+
+flatmap(F, [Hd|Tail]) ->
+ F(Hd) ++ flatmap(F, Tail);
+flatmap(F, []) -> [].
+
+foldl(F, Accu, [Hd|Tail]) ->
+ foldl(F, F(Hd, Accu), Tail);
+foldl(F, Accu, []) -> Accu.
+
+foldr(F, Accu, [Hd|Tail]) ->
+ F(Hd, foldr(F, Accu, Tail));
+foldr(F, Accu, []) -> Accu.
+
+filter(Pred, List) -> [ E || E <- List, Pred(E) ].
+
+zf(F, [Hd|Tail]) ->
+ case F(Hd) of
+ true ->
+ [Hd|zf(F, Tail)];
+ {true,Val} ->
+ [Val|zf(F, Tail)];
+ false ->
+ zf(F, Tail)
+ end;
+zf(F, []) -> [].
+
+foreach(F, [Hd|Tail]) ->
+ F(Hd),
+ foreach(F, Tail);
+foreach(F, []) -> ok.
+
+mapfoldl(F, Accu0, [Hd|Tail]) ->
+ {R,Accu1} = F(Hd, Accu0),
+ {Rs,Accu2} = mapfoldl(F, Accu1, Tail),
+ {[R|Rs],Accu2};
+mapfoldl(F, Accu, []) -> {[],Accu}.
+
+mapfoldr(F, Accu0, [Hd|Tail]) ->
+ {Rs,Accu1} = mapfoldr(F, Accu0, Tail),
+ {R,Accu2} = F(Hd, Accu1),
+ {[R|Rs],Accu2};
+mapfoldr(F, Accu, []) -> {[],Accu}.
+
+takewhile(Pred, [Hd|Tail]) ->
+ case Pred(Hd) of
+ true -> [Hd|takewhile(Pred, Tail)];
+ false -> []
+ end;
+takewhile(Pred, []) -> [].
+
+dropwhile(Pred, [Hd|Tail]) ->
+ case Pred(Hd) of
+ true -> dropwhile(Pred, Tail);
+ false -> [Hd|Tail]
+ end;
+dropwhile(Pred, []) -> [].
+
+splitwith(Pred, List) -> splitwith(Pred, List, []).
+
+splitwith(Pred, [Hd|Tail], Taken) ->
+ case Pred(Hd) of
+ true -> splitwith(Pred, Tail, [Hd|Taken]);
+ false -> {reverse(Taken), [Hd|Tail]}
+ end;
+splitwith(Pred, [], Taken) -> {reverse(Taken),[]}.
+
+%% Versions of the above functions with extra arguments.
+
+all(Pred, Eas, [Hd|Tail]) ->
+ case apply(Pred, [Hd|Eas]) of
+ true -> all(Pred, Eas, Tail);
+ false -> false
+ end;
+all(Pred, Eas, []) -> true.
+
+any(Pred, Eas, [Hd|Tail]) ->
+ case apply(Pred, [Hd|Eas]) of
+ true -> true;
+ false -> any(Pred, Eas, Tail)
+ end;
+any(Pred, Eas, []) -> false.
+
+map(F, Eas, List) -> [ apply(F, [E|Eas]) || E <- List ].
+
+flatmap(F, Eas, [Hd|Tail]) ->
+ apply(F, [Hd|Eas]) ++ flatmap(F, Eas, Tail);
+flatmap(F, Eas, []) -> [].
+
+foldl(F, Eas, Accu, [Hd|Tail]) ->
+ foldl(F, Eas, apply(F, [Hd,Accu|Eas]), Tail);
+foldl(F, Eas, Accu, []) -> Accu.
+
+foldr(F, Eas, Accu, [Hd|Tail]) ->
+ apply(F, [Hd,foldr(F, Eas, Accu, Tail)|Eas]);
+foldr(F, Eas, Accu, []) ->
+ Accu.
+
+filter(Pred, Eas, List) -> [ E || E <- List, apply(Pred, [E|Eas]) ].
+
+zf(F, Eas, [Hd|Tail]) ->
+ case apply(F, [Hd|Eas]) of
+ true ->
+ [Hd|zf(F, Eas, Tail)];
+ {true,Val} ->
+ [Val|zf(F, Eas, Tail)];
+ false ->
+ zf(F, Eas, Tail)
+ end;
+zf(F, Eas, []) -> [].
+
+foreach(F, Eas, [Hd|Tail]) ->
+ apply(F, [Hd|Eas]),
+ foreach(F, Eas, Tail);
+foreach(F, Eas, []) -> ok.
+
+mapfoldl(F, Eas, Accu0, [Hd|Tail]) ->
+ {R,Accu1} = apply(F, [Hd,Accu0|Eas]),
+ {Rs,Accu2} = mapfoldl(F, Eas, Accu1, Tail),
+ {[R|Rs],Accu2};
+mapfoldl(F, Eas, Accu, []) -> {[],Accu}.
+
+mapfoldr(F, Eas, Accu0, [Hd|Tail]) ->
+ {Rs,Accu1} = mapfoldr(F, Eas, Accu0, Tail),
+ {R,Accu2} = apply(F, [Hd,Accu1|Eas]),
+ {[R|Rs],Accu2};
+mapfoldr(F, Eas, Accu, []) -> {[],Accu}.
+
+%% takewhile/2, dropwhile/2 and splitwith/2 do not have versions with
+%% extra arguments as this going to be discontinued.
diff --git a/lib/debugger/test/dbg_ui_SUITE_data/manual_data/src/ordsets1.erl b/lib/debugger/test/dbg_ui_SUITE_data/manual_data/src/ordsets1.erl
new file mode 100644
index 0000000000..ea72150bca
--- /dev/null
+++ b/lib/debugger/test/dbg_ui_SUITE_data/manual_data/src/ordsets1.erl
@@ -0,0 +1,188 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Purpose : Functions for manipulating sets as ordered lists.
+
+%% As yet some of these are not very efficiently written.
+
+-module(ordsets1).
+
+-export([new_set/0,is_set/1,set_to_list/1,list_to_set/1]).
+-export([is_element/2,add_element/2,del_element/2]).
+-export([union/2,union/1,intersection/2,intersection/1]).
+-export([subtract/2,subset/2]).
+
+%% new_set()
+%% Return a new empty ordered set.
+
+new_set() ->
+ [].
+
+%% is_set(Set)
+%% Return 'true' if Set is an ordered set of elements, else 'false'.
+
+is_set([E|Es]) ->
+ is_set(Es, E);
+is_set([]) ->
+ true.
+
+is_set([E2|Es], E1) when E1 < E2 ->
+ is_set(Es, E2);
+is_set([E2|Es], E1) ->
+ false;
+is_set([], E1) ->
+ true.
+
+%% set_to_list(OrdSet)
+%% Return the elements in OrdSet as a list.
+
+set_to_list(S) ->
+ S.
+
+%% list_to_set(List)
+%% Build an ordered set from the elements in List.
+
+list_to_set([E|Es]) ->
+ add_element(E, list_to_set(Es));
+list_to_set([]) ->
+ [].
+
+%% is_element(Element, OrdSet)
+%% Return 'true' if Element is an element of OrdSet, else 'false'.
+
+is_element(E, [H|Es]) when E < H ->
+ false;
+is_element(E, [H|Es]) when E == H ->
+ true;
+is_element(E, [H|Es]) when E > H ->
+ is_element(E, Es);
+is_element(E, []) ->
+ false.
+
+%% add_element(Element, OrdSet)
+%% Return OrdSet with Element inserted in it.
+
+add_element(E, [H|Es]) when E < H ->
+ [E,H|Es];
+add_element(E, [H|Es]) when E == H ->
+ [H|Es];
+add_element(E, [H|Es]) when E > H ->
+ [H|add_element(E, Es)];
+add_element(E, []) ->
+ [E].
+
+%% del_element(Element, OrdSet)
+%% Return OrdSet but with Element removed.
+
+del_element(E, [H|Es]) when E < H ->
+ [H|Es];
+del_element(E, [H|Es]) when E == H ->
+ Es;
+del_element(E, [H|Es]) when E > H ->
+ [H|del_element(E, Es)];
+del_element(E, []) ->
+ [].
+
+%% union(Set1, Set2)
+%% Return the union of Set1 and Set2.
+
+union([H1|Es1], [H2|Es2]) when H1 < H2 ->
+ [H1|union(Es1, [H2|Es2])];
+union([H1|Es1], [H2|Es2]) when H1 == H2 ->
+ [H1|union(Es1, Es2)];
+union([H1|Es1], [H2|Es2]) when H1 > H2 ->
+ [H2|union([H1|Es1], Es2)];
+union([], Es2) ->
+ Es2;
+union(Es1, []) ->
+ Es1.
+
+%% union(OrdSets)
+%% Return the union of the list of sets.
+
+union([S1,S2|Ss]) ->
+ union1(union(S1,S2), Ss);
+union([S]) ->
+ S;
+union([]) ->
+ [].
+
+union1(S1, [S2|Ss]) ->
+ union1(union(S1, S2), Ss);
+union1(S1, []) ->
+ S1.
+
+%% intersection(Set1, Set2)
+%% Return the intersection of Set1 and Set2.
+
+intersection([H1|Es1], [H2|Es2]) when H1 < H2 ->
+ intersection(Es1, [H2|Es2]);
+intersection([H1|Es1], [H2|Es2]) when H1 == H2 ->
+ [H1|intersection(Es1, Es2)];
+intersection([H1|Es1], [H2|Es2]) when H1 > H2 ->
+ intersection([H1|Es1], Es2);
+intersection([], Es2) ->
+ [];
+intersection(Es1, []) ->
+ [].
+
+%% intersection(OrdSets)
+%% Return the intersection of the list of sets.
+
+intersection([S1,S2|Ss]) ->
+ intersection1(intersection(S1,S2), Ss);
+intersection([S]) ->
+ S;
+intersection([]) ->
+ [].
+
+intersection1(S1, [S2|Ss]) ->
+ intersection1(intersection(S1, S2), Ss);
+intersection1(S1, []) ->
+ S1.
+
+%% subtract(Set1, Set2)
+%% Return all and only the elements of Set1 which are not also in Set2.
+
+subtract([H1|Es1], [H2|Es2]) when H1 < H2 ->
+ [H1|subtract(Es1, [H2|Es2])];
+subtract([H1|Es1], [H2|Es2]) when H1 == H2 ->
+ subtract(Es1, Es2);
+subtract([H1|Es1], [H2|Es2]) when H1 > H2 ->
+ subtract([H1|Es1], Es2);
+subtract([], Es2) ->
+ [];
+subtract(Es1, []) ->
+ Es1.
+
+%% subset(Set1, Set2)
+%% Return 'true' when every element of Set1 is also a member of Set2,
+%% else 'false'.
+
+subset([H1|Es1], [H2|Es2]) when H1 < H2 -> %H1 not in Set2
+ false;
+subset([H1|Es1], [H2|Es2]) when H1 == H2 ->
+ subset(Es1, Es2);
+subset([H1|Es1], [H2|Es2]) when H1 > H2 ->
+ subset([H1|Es1], Es2);
+subset([], Es2) ->
+ true;
+subset(Es1, []) ->
+ false.
diff --git a/lib/debugger/test/dbg_ui_SUITE_data/manual_data/src/test.erl b/lib/debugger/test/dbg_ui_SUITE_data/manual_data/src/test.erl
new file mode 100644
index 0000000000..a48a7e112f
--- /dev/null
+++ b/lib/debugger/test/dbg_ui_SUITE_data/manual_data/src/test.erl
@@ -0,0 +1,157 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-module(test).
+
+%%-compile(export_all).
+-export([test1/0,
+ test2/0,
+ test3/0,
+ test4/0,
+ test5/0,
+ test6/1,
+ test7/0,
+ test8/1,
+ test9/0,
+ test10/0,
+ test11/0,
+ test12/1
+ ]).
+
+
+-export([test9_server/1]).
+
+
+test1() ->
+ R1 = lists1:reverse("retep"),
+ R2 = ordsets1:list_to_set([b,c,a,2,4,1]),
+ R3 = lists1:reverse("nilo"),
+ {R1,R2, R3}.
+
+test2() ->
+ R1 = spawn(lists1,reverse,["retep"]),
+ R2 = spawn(ordsets1,list_to_set,[[b,c,a,2,4,1]]),
+ R3 = spawn(lists1,reverse,["nilo"]),
+ {R1,R2, R3}.
+
+
+test3() ->
+ A = a,
+ Pid = spawn(?MODULE, test1,[]),
+ B = b,
+ {A, B, Pid}.
+
+test4() ->
+ Pid = spawn(?MODULE, test1,[]),
+ A = a,
+ B = b,
+ {A, B, Pid}.
+test5() ->
+ L1 = [a,b,c],
+ L = length(L1),
+ A = a,
+ B = b,
+ {A, B, L, L1}.
+
+
+
+test6(0) ->
+ ok;
+test6(N) when N>0 ->
+ spawn(lists1,reverse,["adolfiparisrorsirapifloda"]),
+ test6(N-1).
+
+
+test7() ->
+ CurDirReturn = file:get_cwd(),
+ {ok, CurDir} = CurDirReturn,
+ DirListReturn = file:list_dir(CurDir),
+ {ok, DirList} = DirListReturn,
+ io:format("~w~n",[DirList]).
+
+
+test8(List) ->
+ %% foo
+ %%bar
+ %% foo
+ %%bar
+ %% foo
+ %%bar
+ %% foo
+ %%bar
+
+ L2 = [gamma|List],
+ {L2, List}.
+
+test9() ->
+ S1 = spawn(?MODULE, test9_server,[self()]),
+ S2 = spawn(?MODULE, test9_server,[bongo]),
+ S3 = spawn(?MODULE, test9_server,[42]),
+
+ test9_loop(S1,S2,S3).
+
+test9_loop(S1,S2,S3) ->
+ receive
+ {S1, hej} ->
+ io:format("S1 ~n"),
+ test9_loop(S1,S2,S3);
+ {S2, hej} ->
+ io:format("S2 ~n"),
+ test9_loop(S1,S2,S3);
+ {S3, hej} ->
+ io:format("S3 ~n"),
+ test9_loop(S1,S2,S3)
+ end.
+
+
+test9_server(Pid) ->
+ io:format("started server: ~p~n",[Pid]),
+ test9_server1(Pid).
+
+test9_server1(Pid) ->
+ Pad = {pad, Pid},
+ test9_server2(Pad).
+
+test9_server2(Pad) ->
+ {pad, Pid} = Pad,
+ Pid ! {self(), hej}.
+
+
+
+
+
+test10() ->
+ receive
+ X ->
+ done
+ after 20000 ->
+ timeout
+ end.
+
+test11() ->
+ receive
+ X ->
+ done
+ end.
+
+test12(normal) ->
+ done;
+test12(crash) ->
+ exit(crash).
diff --git a/lib/debugger/test/debugger.spec b/lib/debugger/test/debugger.spec
new file mode 100644
index 0000000000..cc8a5aff37
--- /dev/null
+++ b/lib/debugger/test/debugger.spec
@@ -0,0 +1 @@
+{topcase, {dir, "../debugger_test"}}.
diff --git a/lib/debugger/test/debugger_SUITE.erl b/lib/debugger/test/debugger_SUITE.erl
new file mode 100644
index 0000000000..4bd9057f98
--- /dev/null
+++ b/lib/debugger/test/debugger_SUITE.erl
@@ -0,0 +1,123 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-module(debugger_SUITE).
+
+%% Test break points.
+
+-include("test_server.hrl").
+
+-export([all/1,init_per_testcase/2,fin_per_testcase/2,
+ app_test/1,erts_debug/1,encrypted_debug_info/1,
+ no_abstract_code/1]).
+
+all(suite) ->
+ [app_test,erts_debug,no_abstract_code,encrypted_debug_info].
+
+init_per_testcase(_Case, Config) ->
+ Dog=test_server:timetrap(?t:minutes(0.5)),
+ [{watchdog, Dog}|Config].
+fin_per_testcase(_Case, Config) ->
+ Dog=?config(watchdog, Config),
+ test_server:timetrap_cancel(Dog),
+ ok.
+
+app_test(Config) when is_list(Config) ->
+ ?line ?t:app_test(debugger),
+ ok.
+
+erts_debug(Config) when is_list(Config) ->
+ c:l(erts_debug),
+ ok.
+
+no_abstract_code(Config) when is_list(Config) ->
+ ?line PrivDir = ?config(priv_dir, Config),
+ ?line Simple = filename:join(PrivDir, "simple"),
+ ?line Source = Simple ++ ".erl",
+ ?line BeamFile = Simple ++ ".beam",
+ ?line simple_file(Source),
+
+ %% Compile module without abstract code.
+ CompileFlags = [{outdir,PrivDir}],
+ ?line {ok,_} = compile:file(Source, CompileFlags),
+ ?line error = int:i(Simple),
+
+ %% Cleanup.
+ ?line ok = file:delete(Source),
+ ?line ok = file:delete(BeamFile),
+
+ ok.
+
+encrypted_debug_info(Config) when is_list(Config) ->
+ try begin crypto:start(), crypto:info(), crypto:stop(), ok end of
+ ok ->
+ encrypted_debug_info_1(Config)
+ catch
+ error:_ ->
+ {skip,"The crypto application is missing or broken"}
+ end.
+
+encrypted_debug_info_1(Config) ->
+ ?line PrivDir = ?config(priv_dir, Config),
+ ?line Simple = filename:join(PrivDir, "simple"),
+ ?line Source = Simple ++ ".erl",
+ ?line BeamFile = Simple ++ ".beam",
+ ?line simple_file(Source),
+
+ %% Compile module.
+ Key = "_This a Crypto Key_",
+ CompileFlags = [{outdir,PrivDir},debug_info,{debug_info_key,Key}],
+ ?line {ok,_} = compile:file(Source, CompileFlags),
+
+ %% Interpret module
+ ?line ok = beam_lib:crypto_key_fun(simple_crypto_fun(Key)),
+ ?line {module,simple} = int:i(Simple),
+
+ %% Remove key.
+ ?line {ok,_} = beam_lib:clear_crypto_key_fun(),
+ ?line error = int:i(Simple),
+
+ %% Cleanup.
+ ?line ok = file:delete(Source),
+ ?line ok = file:delete(BeamFile),
+
+ ok.
+
+simple_crypto_fun(Key) ->
+ fun(init) -> ok;
+ ({debug_info, des3_cbc, simple, _}) -> Key
+ end.
+
+
+simple_file(File) ->
+ simple_file(File, simple).
+
+simple_file(File, Module) ->
+ simple_file(File, Module, member).
+
+simple_file(File, Module, F) ->
+ B = list_to_binary(["-module(", atom_to_list(Module), "). "
+ "-export([t/0]). "
+ "t() -> "
+ " t([]). "
+ "t(L) -> "
+ " lists:",
+ atom_to_list(F), "(a, L). "]),
+ ok = file:write_file(File, B).
diff --git a/lib/debugger/test/debugger_test.erl b/lib/debugger/test/debugger_test.erl
new file mode 100644
index 0000000000..a64bed5db1
--- /dev/null
+++ b/lib/debugger/test/debugger_test.erl
@@ -0,0 +1,154 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%%----------------------------------------------------------------------
+%%% Purpose : This is the test module to be used in with the test cases
+%%% in the debugger test document.
+%%%----------------------------------------------------------------------
+
+-module(debugger_test).
+
+
+-export ([installation_ok/0,
+ list/0,
+ fac/1,
+ c_break/1]).
+
+
+-define (INT_DIR, "misc"). % The directory of the Interpreter directory
+-define (INT, "interpreter"). % The Interpreter directory name.
+-define (DBG, "debugger"). % Debugger name
+
+
+%%% installation_ok /0
+%%%
+
+installation_ok () ->
+ debugger_ok (),
+ interpreter_ok ().
+
+
+
+%%% debugger_ok /0
+%%%
+
+debugger_ok () ->
+ L = code:get_path (),
+
+ case debugger_in_codepath (L) of
+ {true, Msg} ->
+ out_put (Msg);
+
+ Other ->
+ out_put (Other)
+ end.
+
+
+
+%%% debugger_in_codepath /2
+%%%
+
+debugger_in_codepath ([]) ->
+ Msg = io_lib:format ("False: ~s not in code path", [?DBG]),
+ lists:flatten (Msg);
+
+debugger_in_codepath ([Path | T]) ->
+ case string:str (Path, ?DBG) =/= 0 of
+ true ->
+ Msg = io_lib:format ("Ok: ~s in code path (~s)", [?DBG, Path]),
+ Msg1 = lists:flatten (Msg),
+ {true, Msg1};
+
+ _Other ->
+ debugger_in_codepath (T)
+ end.
+
+
+
+%%% interpreter_ok /0
+%%%
+
+interpreter_ok () ->
+ Root_dir = code:root_dir (),
+ Misc_dir = filename:join (Root_dir, ?INT_DIR),
+
+ In_misc = case file:list_dir (Misc_dir) of
+ {ok, L} ->
+ lists:member (?INT, L);
+
+ Other ->
+ Other
+ end,
+
+ case In_misc of
+ true ->
+ Msg = io_lib:format ("Ok: ~s is in ~s", [?INT, ?INT_DIR]),
+ Msg1 = lists:flatten (Msg),
+ out_put (Msg1);
+
+ Other1 ->
+ Msg = io_lib:format ("Error: interpreter in misc - ~s", [Other1]),
+ Msg1 = lists:flatten (Msg),
+ out_put (Msg1)
+ end.
+
+
+
+%%% list /0
+%%%
+
+list () ->
+ A = [1, 2, 3, 4, 5],
+ B = [a, b, c, d, e],
+ lists:append (A, B).
+
+
+
+%%% fac /1
+%%%
+
+fac (0) ->
+ 1;
+
+
+fac (N) ->
+ N * fac (N - 1).
+
+
+
+%%% c_break /1
+%%%
+
+c_break (Bindings) ->
+ case int:get_binding ('N', Bindings) of
+ {value, 3} ->
+ true;
+
+ _Other ->
+ false
+ end.
+
+
+
+%%% out_put /1
+%%%
+
+out_put (X) ->
+ io:format ("~n~p~n", [X]).
diff --git a/lib/debugger/test/debugger_testdoc.fm5 b/lib/debugger/test/debugger_testdoc.fm5
new file mode 100644
index 0000000000..56882b8bd5
--- /dev/null
+++ b/lib/debugger/test/debugger_testdoc.fm5
Binary files differ
diff --git a/lib/debugger/test/erl_eval_SUITE.erl b/lib/debugger/test/erl_eval_SUITE.erl
new file mode 100644
index 0000000000..fd4d28b2c7
--- /dev/null
+++ b/lib/debugger/test/erl_eval_SUITE.erl
@@ -0,0 +1,1388 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+
+-module(erl_eval_SUITE).
+-export([all/1]).
+
+-export([guard_1/1, guard_2/1,
+ match_pattern/1,
+ match_bin/1,
+ string_plusplus/1,
+ pattern_expr/1,
+ guard_3/1, guard_4/1,
+ lc/1,
+ simple_cases/1,
+ unary_plus/1,
+ apply_atom/1,
+ otp_5269/1,
+ otp_6539/1,
+ otp_6543/1,
+ otp_6787/1,
+ otp_6977/1,
+ otp_7550/1,
+ otp_8133/1,
+ funs/1,
+ try_catch/1,
+ eval_expr_5/1]).
+
+%%
+%% Define to run outside of test server
+%%
+%%-define(STANDALONE,1).
+
+-import(lists,[concat/1, sort/1]).
+
+-export([count_down/2, count_down_fun/0, do_apply/2,
+ local_func/3, local_func_value/2]).
+
+-ifdef(STANDALONE).
+-define(config(A,B),config(A,B)).
+-export([config/2]).
+-define(line, noop, ).
+config(priv_dir,_) ->
+ ".".
+-else.
+-include("test_server.hrl").
+-export([init_per_testcase/2, fin_per_testcase/2]).
+% Default timetrap timeout (set in init_per_testcase).
+-define(default_timeout, ?t:minutes(1)).
+init_per_testcase(_Case, Config) ->
+ ?line Dog = ?t:timetrap(?default_timeout),
+ [{watchdog, Dog} | Config].
+fin_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ test_server:timetrap_cancel(Dog),
+ ok.
+-endif.
+
+all(doc) ->
+ ["Test cases for the 'erl_eval' module."];
+all(suite) ->
+ [guard_1, guard_2, match_pattern, string_plusplus, pattern_expr,
+ match_bin, guard_3, guard_4,
+ lc, simple_cases, unary_plus, apply_atom, otp_5269, otp_6539, otp_6543,
+ otp_6787, otp_6977, otp_7550, otp_8133, funs, try_catch, eval_expr_5].
+
+guard_1(doc) ->
+ ["(OTP-2405)"];
+guard_1(suite) ->
+ [];
+guard_1(Config) when is_list(Config) ->
+ ?line {ok,Tokens ,_} =
+ erl_scan:string("if a+4 == 4 -> yes; true -> no end. "),
+ ?line {ok, [Expr]} = erl_parse:parse_exprs(Tokens),
+ ?line no = guard_1_compiled(),
+ ?line {value, no, []} = erl_eval:expr(Expr, []),
+ ok.
+
+guard_1_compiled() ->
+ if a+4 == 4 -> yes; true -> no end.
+
+guard_2(doc) ->
+ ["Similar to guard_1, but type-correct"];
+guard_2(suite) ->
+ [];
+guard_2(Config) when is_list(Config) ->
+ ?line {ok,Tokens ,_} =
+ erl_scan:string("if 6+4 == 4 -> yes; true -> no end. "),
+ ?line {ok, [Expr]} = erl_parse:parse_exprs(Tokens),
+ ?line no = guard_2_compiled(),
+ ?line {value, no, []} = erl_eval:expr(Expr, []),
+ ok.
+
+guard_2_compiled() ->
+ if 6+4 == 4 -> yes; true -> no end.
+
+string_plusplus(doc) ->
+ ["OTP-3069: syntactic sugar string ++ ..."];
+string_plusplus(suite) ->
+ [];
+string_plusplus(Config) when is_list(Config) ->
+ ?line check(fun() -> case "abc" of "ab" ++ L -> L end end,
+ "case \"abc\" of \"ab\" ++ L -> L end. ",
+ "c"),
+ ?line check(fun() -> case "abcde" of "ab" ++ "cd" ++ L -> L end end,
+ "case \"abcde\" of \"ab\" ++ \"cd\" ++ L -> L end. ",
+ "e"),
+ ?line check(fun() -> case "abc" of [97, 98] ++ L -> L end end,
+ "case \"abc\" of [97, 98] ++ L -> L end. ",
+ "c"),
+ ok.
+
+match_pattern(doc) ->
+ ["OTP-2983: match operator in pattern"];
+match_pattern(suite) ->
+ [];
+match_pattern(Config) when is_list(Config) ->
+ ?line check(fun() -> case {a, b} of {a, _X}=Y -> {x,Y} end end,
+ "case {a, b} of {a, X}=Y -> {x,Y} end. ",
+ {x, {a, b}}),
+ ?line check(fun() -> case {a, b} of Y={a, _X} -> {x,Y} end end,
+ "case {a, b} of Y={a, X} -> {x,Y} end. ",
+ {x, {a, b}}),
+ ?line check(fun() -> case {a, b} of Y={a, _X}=Z -> {Z,Y} end end,
+ "case {a, b} of Y={a, X}=Z -> {Z,Y} end. ",
+ {{a, b}, {a, b}}),
+ ?line check(fun() -> A = 4, B = 28, <<13:(A+(X=B))>>, X end,
+ "begin A = 4, B = 28, <<13:(A+(X=B))>>, X end.",
+ 28),
+ ok.
+
+match_bin(doc) ->
+ ["binary match problems"];
+match_bin(suite) ->
+ [];
+match_bin(Config) when is_list(Config) ->
+ ?line check(fun() -> <<"abc">> = <<"abc">> end,
+ "<<\"abc\">> = <<\"abc\">>. ",
+ <<"abc">>),
+ ?line check(fun() ->
+ <<Size,B:Size/binary,Rest/binary>> = <<2,"AB","CD">>,
+ {Size,B,Rest}
+ end,
+ "begin <<Size,B:Size/binary,Rest/binary>> = <<2,\"AB\",\"CD\">>, "
+ "{Size,B,Rest} end. ",
+ {2,<<"AB">>,<<"CD">>}),
+ ok.
+
+pattern_expr(doc) ->
+ ["OTP-3144: compile-time expressions in pattern"];
+pattern_expr(suite) ->
+ [];
+pattern_expr(Config) when is_list(Config) ->
+ ?line check(fun() -> case 4 of 2+2 -> ok end end,
+ "case 4 of 2+2 -> ok end. ",
+ ok),
+ ?line check(fun() -> case 2 of +2 -> ok end end,
+ "case 2 of +2 -> ok end. ",
+ ok),
+ ok.
+
+guard_3(doc) ->
+ ["OTP-4518."];
+guard_3(suite) ->
+ [];
+guard_3(Config) when is_list(Config) ->
+ ?line check(fun() -> if false -> false; true -> true end end,
+ "if false -> false; true -> true end.",
+ true),
+ ?line check(fun() -> if <<"hej">> == <<"hopp">> -> true;
+ true -> false end end,
+ "begin if <<\"hej\">> == <<\"hopp\">> -> true;
+ true -> false end end.",
+ false),
+ ?line check(fun() -> if <<"hej">> == <<"hej">> -> true;
+ true -> false end end,
+ "begin if <<\"hej\">> == <<\"hej\">> -> true;
+ true -> false end end.",
+ true),
+ ok.
+
+guard_4(doc) ->
+ ["OTP-4885."];
+guard_4(suite) ->
+ [];
+guard_4(Config) when is_list(Config) ->
+ ?line check(fun() -> if {erlang,'+'}(3,a) -> true ; true -> false end end,
+ "if {erlang,'+'}(3,a) -> true ; true -> false end.",
+ false),
+ ?line check(fun() -> if {erlang,is_integer}(3) -> true ; true -> false end
+ end,
+ "if {erlang,is_integer}(3) -> true ; true -> false end.",
+ true),
+ ?line check(fun() -> [X || X <- [1,2,3], erlang:is_integer(X)] end,
+ "[X || X <- [1,2,3], erlang:is_integer(X)].",
+ [1,2,3]),
+ ?line check(fun() -> if is_atom(is_integer(a)) -> true ; true -> false end
+ end,
+ "if is_atom(is_integer(a)) -> true ; true -> false end.",
+ true),
+ ?line check(fun() -> if {erlang,is_atom}({erlang,is_integer}(a)) -> true;
+ true -> false end end,
+ "if {erlang,is_atom}({erlang,is_integer}(a)) -> true; "
+ "true -> false end.",
+ true),
+ ?line check(fun() -> if is_atom(3+a) -> true ; true -> false end end,
+ "if is_atom(3+a) -> true ; true -> false end.",
+ false),
+ ?line check(fun() -> if erlang:is_atom(3+a) -> true ; true -> false end
+ end,
+ "if erlang:is_atom(3+a) -> true ; true -> false end.",
+ false),
+ ok.
+
+
+lc(doc) ->
+ ["OTP-4518."];
+lc(suite) ->
+ [];
+lc(Config) when is_list(Config) ->
+ ?line check(fun() -> X = 32, [X || X <- [1,2,3]] end,
+ "begin X = 32, [X || X <- [1,2,3]] end.",
+ [1,2,3]),
+ ?line check(fun() -> X = 32,
+ [X || <<X:X>> <- [<<1:32>>,<<2:32>>,<<3:8>>]] end,
+ %% "binsize variable" ^
+ "begin X = 32,
+ [X || <<X:X>> <- [<<1:32>>,<<2:32>>,<<3:8>>]] end.",
+ [1,2]),
+ ?line check(fun() -> Y = 13,[X || {X,Y} <- [{1,2}]] end,
+ "begin Y = 13,[X || {X,Y} <- [{1,2}]] end.",
+ [1]),
+ ?line error_check("begin [A || X <- [{1,2}], 1 == A] end.",
+ {unbound_var,'A'}),
+ ?line error_check("begin X = 32,
+ [{Y,W} || X <- [1,2,32,Y=4], Z <- [1,2,W=3]] end.",
+ {unbound_var,'Y'}),
+ ?line error_check("begin X = 32,<<A:B>> = <<100:X>> end.",
+ {unbound_var,'B'}),
+ ?line check(fun() -> [X || X <- [1,2,3,4], not (X < 2)] end,
+ "begin [X || X <- [1,2,3,4], not (X < 2)] end.",
+ [2,3,4]),
+ ?line check(fun() -> [X || X <- [true,false], X] end,
+ "[X || X <- [true,false], X].", [true]),
+ ok.
+
+simple_cases(doc) ->
+ ["Simple cases, just to cover some code."];
+simple_cases(suite) ->
+ [];
+simple_cases(Config) when is_list(Config) ->
+ ?line check(fun() -> A = $C end, "A = $C.", $C),
+ %% ?line check(fun() -> A = 3.14 end, "A = 3.14.", 3.14),
+ ?line check(fun() -> self() ! a, A = receive a -> true end end,
+ "begin self() ! a, A = receive a -> true end end.",
+ true),
+ ?line check(fun() -> c:flush(), self() ! a, self() ! b, self() ! c,
+ receive b -> b end,
+ {messages, [a,c]} =
+ erlang:process_info(self(), messages),
+ c:flush() end,
+ "begin c:flush(), self() ! a, self() ! b, self() ! c,"
+ "receive b -> b end,"
+ "{messages, [a,c]} ="
+ " erlang:process_info(self(), messages), c:flush() end.",
+ ok),
+ ?line check(fun() -> self() ! a, A = receive a -> true
+ after 0 -> false end end,
+ "begin self() ! a, A = receive a -> true"
+ " after 0 -> false end end.",
+ true),
+ ?line check(fun() -> c:flush(), self() ! a, self() ! b, self() ! c,
+ receive b -> b after 0 -> true end,
+ {messages, [a,c]} =
+ erlang:process_info(self(), messages),
+ c:flush() end,
+ "begin c:flush(), self() ! a, self() ! b, self() ! c,"
+ "receive b -> b after 0 -> true end,"
+ "{messages, [a,c]} ="
+ " erlang:process_info(self(), messages), c:flush() end.",
+ ok),
+ ?line check(fun() -> receive _ -> true after 10 -> false end end,
+ "receive _ -> true after 10 -> false end.",
+ false),
+ ?line check(fun() -> F = fun(A) -> A end, true = 3 == F(3) end,
+ "begin F = fun(A) -> A end, true = 3 == F(3) end.",
+ true),
+ ?line check(fun() -> F = fun(A) -> A end, true = 3 == apply(F, [3]) end,
+ "begin F = fun(A) -> A end, true = 3 == apply(F,[3]) end.",
+ true),
+ ?line check(fun() -> catch throw(a) end, "catch throw(a).", a),
+ ?line check(fun() -> catch a end, "catch a.", a),
+ ?line check(fun() -> 4 == 3 end, "4 == 3.", false),
+ ?line check(fun() -> not true end, "not true.", false),
+ ?line check(fun() -> -3 end, "-3.", -3),
+
+ ?line error_check("3.0 = 4.0.", {badmatch,4.0}),
+ ?line check(fun() -> <<(3.0+2.0):32/float>> = <<5.0:32/float>> end,
+ "<<(3.0+2.0):32/float>> = <<5.0:32/float>>.",
+ <<5.0:32/float>>),
+
+ ?line check(fun() -> false andalso kludd end, "false andalso kludd.",
+ false),
+ ?line check(fun() -> true andalso true end, "true andalso true.",
+ true),
+ ?line check(fun() -> true andalso false end, "true andalso false.",
+ false),
+ ?line check(fun() -> true andalso kludd end, "true andalso kludd.",
+ kludd),
+ ?line error_check("kladd andalso kludd.", {badarg,kladd}),
+
+ ?line check(fun() -> if false andalso kludd -> a; true -> b end end,
+ "if false andalso kludd -> a; true -> b end.",
+ b),
+ ?line check(fun() -> if true andalso true -> a; true -> b end end,
+ "if true andalso true -> a; true -> b end.",
+ a),
+ ?line check(fun() -> if true andalso false -> a; true -> b end end,
+ "if true andalso false -> a; true -> b end.",
+ b),
+
+ ?line check(fun() -> true orelse kludd end,
+ "true orelse kludd.", true),
+ ?line check(fun() -> false orelse false end,
+ "false orelse false.", false),
+ ?line check(fun() -> false orelse true end,
+ "false orelse true.", true),
+ ?line check(fun() -> false orelse kludd end,
+ "false orelse kludd.", kludd),
+ ?line error_check("kladd orelse kludd.", {badarg,kladd}),
+ ?line error_check("[X || X <- [1,2,3], begin 1 end].",{bad_filter,1}),
+ ?line error_check("[X || X <- a].",{bad_generator,a}),
+
+ ?line check(fun() -> if true orelse kludd -> a; true -> b end end,
+ "if true orelse kludd -> a; true -> b end.", a),
+ ?line check(fun() -> if false orelse false -> a; true -> b end end,
+ "if false orelse false -> a; true -> b end.", b),
+ ?line check(fun() -> if false orelse true -> a; true -> b end end,
+ "if false orelse true -> a; true -> b end.", a),
+
+ ?line check(fun() -> [X || X <- [1,2,3], X+2] end,
+ "[X || X <- [1,2,3], X+2].", []),
+
+ ?line check(fun() -> [X || X <- [1,2,3], [X] == [X || X <- [2]]] end,
+ "[X || X <- [1,2,3], [X] == [X || X <- [2]]].",
+ [2]),
+ ?line check(fun() -> F = fun(1) -> ett; (2) -> zwei end,
+ ett = F(1), zwei = F(2) end,
+ "begin F = fun(1) -> ett; (2) -> zwei end,
+ ett = F(1), zwei = F(2) end.",
+ zwei),
+ ?line check(fun() -> F = fun(X) when X == 1 -> ett;
+ (X) when X == 2 -> zwei end,
+ ett = F(1), zwei = F(2) end,
+ "begin F = fun(X) when X == 1 -> ett;
+ (X) when X == 2 -> zwei end,
+ ett = F(1), zwei = F(2) end.",
+ zwei),
+ ?line error_check("begin F = fun(1) -> ett end, zwei = F(2) end.",
+ function_clause),
+ ?line check(fun() -> if length([1]) == 1 -> yes;
+ true -> no end end,
+ "if length([1]) == 1 -> yes;
+ true -> no end.",
+ yes),
+ ?line check(fun() -> if is_integer(3) -> true; true -> false end end,
+ "if is_integer(3) -> true; true -> false end.", true),
+ ?line check(fun() -> if integer(3) -> true; true -> false end end,
+ "if integer(3) -> true; true -> false end.", true),
+ ?line check(fun() -> if is_float(3) -> true; true -> false end end,
+ "if is_float(3) -> true; true -> false end.", false),
+ ?line check(fun() -> if float(3) -> true; true -> false end end,
+ "if float(3) -> true; true -> false end.", false),
+ ?line check(fun() -> if is_number(3) -> true; true -> false end end,
+ "if is_number(3) -> true; true -> false end.", true),
+ ?line check(fun() -> if number(3) -> true; true -> false end end,
+ "if number(3) -> true; true -> false end.", true),
+ ?line check(fun() -> if is_atom(a) -> true; true -> false end end,
+ "if is_atom(a) -> true; true -> false end.", true),
+ ?line check(fun() -> if atom(a) -> true; true -> false end end,
+ "if atom(a) -> true; true -> false end.", true),
+ ?line check(fun() -> if is_list([]) -> true; true -> false end end,
+ "if is_list([]) -> true; true -> false end.", true),
+ ?line check(fun() -> if list([]) -> true; true -> false end end,
+ "if list([]) -> true; true -> false end.", true),
+ ?line check(fun() -> if is_tuple({}) -> true; true -> false end end,
+ "if is_tuple({}) -> true; true -> false end.", true),
+ ?line check(fun() -> if tuple({}) -> true; true -> false end end,
+ "if tuple({}) -> true; true -> false end.", true),
+ ?line check(fun() -> if is_pid(self()) -> true; true -> false end end,
+ "if is_pid(self()) -> true; true -> false end.", true),
+ ?line check(fun() -> if pid(self()) -> true; true -> false end end,
+ "if pid(self()) -> true; true -> false end.", true),
+ ?line check(fun() -> R = make_ref(), if is_reference(R) -> true;
+ true -> false end end,
+ "begin R = make_ref(), if is_reference(R) -> true;"
+ "true -> false end end.", true),
+ ?line check(fun() -> R = make_ref(), if reference(R) -> true;
+ true -> false end end,
+ "begin R = make_ref(), if reference(R) -> true;"
+ "true -> false end end.", true),
+ ?line check(fun() -> if is_port(a) -> true; true -> false end end,
+ "if is_port(a) -> true; true -> false end.", false),
+ ?line check(fun() -> if port(a) -> true; true -> false end end,
+ "if port(a) -> true; true -> false end.", false),
+ ?line check(fun() -> if is_function(a) -> true; true -> false end end,
+ "if is_function(a) -> true; true -> false end.", false),
+ ?line check(fun() -> if function(a) -> true; true -> false end end,
+ "if function(a) -> true; true -> false end.", false),
+ ?line check(fun() -> if is_binary(<<>>) -> true; true -> false end end,
+ "if is_binary(<<>>) -> true; true -> false end.", true),
+ ?line check(fun() -> if binary(<<>>) -> true; true -> false end end,
+ "if binary(<<>>) -> true; true -> false end.", true),
+ ?line check(fun() -> if is_integer(a) == true -> yes;
+ true -> no end end,
+ "if is_integer(a) == true -> yes;
+ true -> no end.",
+ no),
+ ?line check(fun() -> if [] -> true; true -> false end end,
+ "if [] -> true; true -> false end.", false),
+ ?line error_check("if lists:member(1,[1]) -> true; true -> false end.",
+ illegal_guard_expr),
+ ?line error_check("if false -> true end.", if_clause),
+ ?line check(fun() -> if a+b -> true; true -> false end end,
+ "if a + b -> true; true -> false end.", false),
+ ?line check(fun() -> if + b -> true; true -> false end end,
+ "if + b -> true; true -> false end.", false),
+ ?line error_check("case foo of bar -> true end.", {case_clause,foo}),
+ ?line error_check("case 4 of 2+a -> true; _ -> false end.",
+ illegal_pattern),
+ ?line error_check("case 4 of +a -> true; _ -> false end.",
+ illegal_pattern),
+ ?line check(fun() -> case a of
+ X when X == b -> one;
+ X when X == a -> two
+ end end,
+ "begin case a of
+ X when X == b -> one;
+ X when X == a -> two
+ end end.", two),
+ ?line error_check("3 = 4.", {badmatch,4}),
+ ?line error_check("a = 3.", {badmatch,3}),
+ %% ?line error_check("3.1 = 2.7.",{badmatch,2.7}),
+ ?line error_check("$c = 4.", {badmatch,4}),
+ ?line check(fun() -> $c = $c end, "$c = $c.", $c),
+ ?line check(fun() -> _ = bar end, "_ = bar.", bar),
+ ?line check(fun() -> A = 14, A = 14 end,
+ "begin A = 14, A = 14 end.", 14),
+ ?line error_check("begin A = 14, A = 16 end.", {badmatch,16}),
+ ?line error_check("\"hej\" = \"san\".", {badmatch,"san"}),
+ ?line check(fun() -> "hej" = "hej" end,
+ "\"hej\" = \"hej\".", "hej"),
+ ?line error_check("[] = [a].", {badmatch,[a]}),
+ ?line check(fun() -> [] = [] end, "[] = [].", []),
+ ?line error_check("[a] = [].", {badmatch,[]}),
+ ?line error_check("{a,b} = 34.", {badmatch,34}),
+ ?line check(fun() -> <<X:7>> = <<8:7>>, X end,
+ "begin <<X:7>> = <<8:7>>, X end.", 8),
+ ?line error_check("<<34:32>> = \"hej\".", {badmatch,"hej"}),
+ ?line check(fun() -> trunc((1 * 3 div 3 + 4 - 3) / 1) rem 2 end,
+ "begin trunc((1 * 3 div 3 + 4 - 3) / 1) rem 2 end.", 0),
+ ?line check(fun() -> (2#101 band 2#10101) bor (2#110 bxor 2#010) end,
+ "(2#101 band 2#10101) bor (2#110 bxor 2#010).", 5),
+ ?line check(fun() -> (2#1 bsl 4) + (2#10000 bsr 3) end,
+ "(2#1 bsl 4) + (2#10000 bsr 3).", 18),
+ ?line check(fun() -> ((1<3) and ((1 =:= 2) or (1 =/= 2))) xor (1=<2) end,
+ "((1<3) and ((1 =:= 2) or (1 =/= 2))) xor (1=<2).", false),
+ ?line check(fun() -> (a /= b) or (2 > 4) or (3 >= 3) end,
+ "(a /= b) or (2 > 4) or (3 >= 3).", true),
+ ?line check(fun() -> "hej" ++ "san" =/= "hejsan" -- "san" end,
+ "\"hej\" ++ \"san\" =/= \"hejsan\" -- \"san\".", true),
+ ?line check(fun() -> (bnot 1) < -0 end, "(bnot (+1)) < -0.", true),
+ ok.
+
+unary_plus(doc) ->
+ ["OTP-4929. Unary plus rejects non-numbers."];
+unary_plus(suite) ->
+ [];
+unary_plus(Config) when is_list(Config) ->
+ ?line check(fun() -> F = fun(X) -> + X end,
+ true = -1 == F(-1) end,
+ "begin F = fun(X) -> + X end,"
+ " true = -1 == F(-1) end.", true, ['F'], none, none),
+ ?line error_check("+a.", badarith),
+ ok.
+
+apply_atom(doc) ->
+ ["OTP-5064. Can no longer apply atoms."];
+apply_atom(suite) ->
+ [];
+apply_atom(Config) when is_list(Config) ->
+ ?line error_check("[X || X <- [[1],[2]],
+ begin L = length, L(X) =:= 1 end].",
+ {badfun,length}),
+ ok.
+
+otp_5269(doc) ->
+ ["OTP-5269. Bugs in the bit syntax."];
+otp_5269(suite) ->
+ [];
+otp_5269(Config) when is_list(Config) ->
+ ?line check(fun() -> L = 8,
+ F = fun(<<A:L,B:A>>) -> B end,
+ F(<<16:8, 7:16>>)
+ end,
+ "begin
+ L = 8, F = fun(<<A:L,B:A>>) -> B end, F(<<16:8, 7:16>>)
+ end.",
+ 7),
+ ?line check(fun() -> L = 8,
+ F = fun(<<L:L,B:L>>) -> B end,
+ F(<<16:8, 7:16>>)
+ end,
+ "begin
+ L = 8, F = fun(<<L:L,B:L>>) -> B end, F(<<16:8, 7:16>>)
+ end.",
+ 7),
+ ?line check(fun() -> L = 8, <<A:L,B:A>> = <<16:8, 7:16>>, B end,
+ "begin L = 8, <<A:L,B:A>> = <<16:8, 7:16>>, B end.",
+ 7),
+ ?line error_check("begin L = 8, <<L:L,B:L>> = <<16:8, 7:16>> end.",
+ {badmatch,<<16:8,7:16>>}),
+
+ ?line error_check("begin <<L:16,L:L>> = <<16:16,8:16>>, L end.",
+ {badmatch, <<16:16,8:16>>}),
+ ?line check(fun() -> U = 8, (fun(<<U:U>>) -> U end)(<<32:8>>) end,
+ "begin U = 8, (fun(<<U:U>>) -> U end)(<<32:8>>) end.",
+ 32),
+ ?line check(fun() -> U = 8, [U || <<U:U>> <- [<<32:8>>]] end,
+ "begin U = 8, [U || <<U:U>> <- [<<32:8>>]] end.",
+ [32]),
+ ?line error_check("(fun({3,<<A:32,A:32>>}) -> a end)
+ ({3,<<17:32,19:32>>}).",
+ function_clause),
+ ?line check(fun() -> [X || <<A:8,
+ B:A>> <- [<<16:8,19:16>>],
+ <<X:8>> <- [<<B:8>>]] end,
+ "[X || <<A:8,
+ B:A>> <- [<<16:8,19:16>>],
+ <<X:8>> <- [<<B:8>>]].",
+ [19]),
+ ok.
+
+otp_6539(doc) ->
+ ["OTP-6539. try/catch bugs."];
+otp_6539(suite) ->
+ [];
+otp_6539(Config) when is_list(Config) ->
+ ?line check(fun() ->
+ F = fun(A,B) ->
+ try A+B
+ catch _:_ -> dontthinkso
+ end
+ end,
+ lists:zipwith(F, [1,2], [2,3])
+ end,
+ "begin
+ F = fun(A,B) ->
+ try A+B
+ catch _:_ -> dontthinkso
+ end
+ end,
+ lists:zipwith(F, [1,2], [2,3])
+ end.",
+ [3, 5]),
+ ok.
+
+otp_6543(doc) ->
+ ["OTP-6543. bitlevel binaries."];
+otp_6543(suite) ->
+ [];
+otp_6543(Config) when is_list(Config) ->
+ ?line check(fun() ->
+ << <<X>> || <<X>> <- [1,2,3] >>
+ end,
+ "<< <<X>> || <<X>> <- [1,2,3] >>.",
+ <<>>),
+ ?line check(fun() ->
+ << <<X>> || X <- [1,2,3] >>
+ end,
+ "<< <<X>> || X <- [1,2,3] >>.",
+ <<1,2,3>>),
+ ?line check(fun() ->
+ << <<X:8>> || <<X:2>> <= <<"hej">> >>
+ end,
+ "<< <<X:8>> || <<X:2>> <= <<\"hej\">> >>.",
+ <<1,2,2,0,1,2,1,1,1,2,2,2>>),
+ ?line check(fun() ->
+ << <<X:8>> ||
+ <<65,X:4>> <= <<65,7:4,65,3:4,66,8:4>> >>
+ end,
+ "<< <<X:8>> ||
+ <<65,X:4>> <= <<65,7:4,65,3:4,66,8:4>> >>.",
+ <<7,3>>),
+ ?line check(fun() -> <<34:18/big>> end,
+ "<<34:18/big>>.",
+ <<0,8,2:2>>),
+ ?line check(fun() -> <<34:18/big-unit:2>> end,
+ "<<34:18/big-unit:2>>.",
+ <<0,0,0,2,2:4>>),
+ ?line check(fun() -> <<34:18/little>> end,
+ "<<34:18/little>>.",
+ <<34,0,0:2>>),
+ ?line case eval_string("<<34:18/native>>.") of
+ <<0,8,2:2>> -> ok;
+ <<34,0,0:2>> -> ok
+ end,
+ ?line check(fun() -> <<34:18/big-signed>> end,
+ "<<34:18/big-signed>>.",
+ <<0,8,2:2>>),
+ ?line check(fun() -> <<34:18/little-signed>> end,
+ "<<34:18/little-signed>>.",
+ <<34,0,0:2>>),
+ ?line case eval_string("<<34:18/native-signed>>.") of
+ <<0,8,2:2>> -> ok;
+ <<34,0,0:2>> -> ok
+ end,
+ ?line check(fun() -> <<34:18/big-unsigned>> end,
+ "<<34:18/big-unsigned>>.",
+ <<0,8,2:2>>),
+ ?line check(fun() -> <<34:18/little-unsigned>> end,
+ "<<34:18/little-unsigned>>.",
+ <<34,0,0:2>>),
+ ?line case eval_string("<<34:18/native-unsigned>>.") of
+ <<0,8,2:2>> -> ok;
+ <<34,0,0:2>> -> ok
+ end,
+ ?line check(fun() -> <<3.14:32/float-big>> end,
+ "<<3.14:32/float-big>>.",
+ <<64,72,245,195>>),
+ ?line check(fun() -> <<3.14:32/float-little>> end,
+ "<<3.14:32/float-little>>.",
+ <<195,245,72,64>>),
+ ?line case eval_string("<<3.14:32/float-native>>.") of
+ <<64,72,245,195>> -> ok;
+ <<195,245,72,64>> -> ok
+ end,
+ ?line error_check("<<(<<17,3:2>>)/binary>>.", badarg),
+ ?line check(fun() -> <<(<<17,3:2>>)/bitstring>> end,
+ "<<(<<17,3:2>>)/bitstring>>.",
+ <<17,3:2>>),
+ ?line check(fun() -> <<(<<17,3:2>>):10/bitstring>> end,
+ "<<(<<17,3:2>>):10/bitstring>>.",
+ <<17,3:2>>),
+ ?line check(fun() -> <<<<344:17>>/binary-unit:17>> end,
+ "<<<<344:17>>/binary-unit:17>>.",
+ <<344:17>>),
+
+ ?line check(fun() -> <<X:18/big>> = <<34:18/big>>, X end,
+ "begin <<X:18/big>> = <<34:18/big>>, X end.",
+ 34),
+ ?line check(fun() -> <<X:18/big-unit:2>> = <<34:18/big-unit:2>>, X end,
+ "begin <<X:18/big-unit:2>> = <<34:18/big-unit:2>>, X end.",
+ 34),
+ ?line check(fun() -> <<X:18/little>> = <<34:18/little>>, X end,
+ "begin <<X:18/little>> = <<34:18/little>>, X end.",
+ 34),
+ ?line check(fun() -> <<X:18/native>> = <<34:18/native>>, X end,
+ "begin <<X:18/native>> = <<34:18/native>>, X end.",
+ 34),
+ ?line check(fun() -> <<X:18/big-signed>> = <<34:18/big-signed>>, X end,
+ "begin <<X:18/big-signed>> = <<34:18/big-signed>>, X end.",
+ 34),
+ ?line check(fun() -> <<X:18/little-signed>> = <<34:18/little-signed>>,
+ X end,
+ "begin <<X:18/little-signed>> = <<34:18/little-signed>>,
+ X end.",
+ 34),
+ ?line check(fun() -> <<X:18/native-signed>> = <<34:18/native-signed>>,
+ X end,
+ "begin <<X:18/native-signed>> = <<34:18/native-signed>>,
+ X end.",
+ 34),
+ ?line check(fun() -> <<X:18/big-unsigned>> = <<34:18/big-unsigned>>,
+ X end,
+ "begin <<X:18/big-unsigned>> = <<34:18/big-unsigned>>,
+ X end.",
+ 34),
+ ?line check(fun() ->
+ <<X:18/little-unsigned>> = <<34:18/little-unsigned>>,
+ X end,
+ "begin <<X:18/little-unsigned>> = <<34:18/little-unsigned>>,
+ X end.",
+ 34),
+ ?line check(fun() ->
+ <<X:18/native-unsigned>> = <<34:18/native-unsigned>>,
+ X end,
+ "begin <<X:18/native-unsigned>> = <<34:18/native-unsigned>>,
+ X end.",
+ 34),
+ ?line check(fun() -> <<X:32/float-big>> = <<2.0:32/float-big>>, X end,
+ "begin <<X:32/float-big>> = <<2.0:32/float-big>>,
+ X end.",
+ 2.0),
+ ?line check(fun() -> <<X:32/float-little>> = <<2.0:32/float-little>>,
+ X end,
+ "begin <<X:32/float-little>> = <<2.0:32/float-little>>,
+ X end.",
+ 2.0),
+ ?line check(fun() -> <<X:32/float-native>> = <<2.0:32/float-native>>,
+ X end,
+ "begin <<X:32/float-native>> = <<2.0:32/float-native>>,
+ X end.",
+ 2.0),
+
+ ?line check(
+ fun() ->
+ [X || <<"hej",X:8>> <= <<"hej",8,"san",9,"hej",17,"hej">>]
+ end,
+ "[X || <<\"hej\",X:8>> <=
+ <<\"hej\",8,\"san\",9,\"hej\",17,\"hej\">>].",
+ [8,17]),
+ ?line check(
+ fun() ->
+ L = 8, << <<B:32>> || <<L:L,B:L>> <= <<16:8, 7:16>> >>
+ end,
+ "begin L = 8, << <<B:32>> || <<L:L,B:L>> <= <<16:8, 7:16>> >>
+ end.",
+ <<0,0,0,7>>),
+ %% Test the Value part of a binary segment.
+ %% "Old" bugs have been fixed (partial_eval is called on Value).
+ ?line check(fun() -> [ 3 || <<17/float>> <= <<17.0/float>>] end,
+ "[ 3 || <<17/float>> <= <<17.0/float>>].",
+ [3]),
+ ?line check(fun() -> [ 3 || <<17/float>> <- [<<17.0/float>>]] end,
+ "[ 3 || <<17/float>> <- [<<17.0/float>>]].",
+ [3]),
+ ?line check(fun() -> [ X || <<17/float,X:3>> <= <<17.0/float,2:3>>] end,
+ "[ X || <<17/float,X:3>> <= <<17.0/float,2:3>>].",
+ [2]),
+ ?line check(fun() ->
+ [ foo || <<(1 bsl 1023)/float>> <= <<(1 bsl 1023)/float>>]
+ end,
+ "[ foo || <<(1 bsl 1023)/float>> <= <<(1 bsl 1023)/float>>].",
+ [foo]),
+ ?line check(fun() ->
+ [ foo || <<(1 bsl 1023)/float>> <- [<<(1 bsl 1023)/float>>]]
+ end,
+ "[ foo || <<(1 bsl 1023)/float>> <- [<<(1 bsl 1023)/float>>]].",
+ [foo]),
+ ?line error_check("[ foo || <<(1 bsl 1024)/float>> <-
+ [<<(1 bsl 1024)/float>>]].",
+ badarg),
+ ?line check(fun() ->
+ [ foo || <<(1 bsl 1024)/float>> <- [<<(1 bsl 1023)/float>>]]
+ end,
+ "[ foo || <<(1 bsl 1024)/float>> <-
+ [<<(1 bsl 1023)/float>>]].",
+ []),
+ ?line check(fun() ->
+ [ foo || <<(1 bsl 1024)/float>> <= <<(1 bsl 1023)/float>>]
+ end,
+ "[ foo || <<(1 bsl 1024)/float>> <=
+ <<(1 bsl 1023)/float>>].",
+ []),
+ ?line check(fun() ->
+ L = 8,
+ [{L,B} || <<L:L,B:L/float>> <= <<32:8,7:32/float>>]
+ end,
+ "begin L = 8,
+ [{L,B} || <<L:L,B:L/float>> <= <<32:8,7:32/float>>]
+ end.",
+ [{32,7.0}]),
+ ?line check(fun() ->
+ L = 8,
+ [{L,B} || <<L:L,B:L/float>> <- [<<32:8,7:32/float>>]]
+ end,
+ "begin L = 8,
+ [{L,B} || <<L:L,B:L/float>> <- [<<32:8,7:32/float>>]]
+ end.",
+ [{32,7.0}]),
+ ?line check(fun() ->
+ [foo || <<"s">> <= <<"st">>]
+ end,
+ "[foo || <<\"s\">> <= <<\"st\">>].",
+ [foo]),
+ ?line check(fun() -> <<_:32>> = <<17:32>> end,
+ "<<_:32>> = <<17:32>>.",
+ <<17:32>>),
+ ?line check(fun() -> [foo || <<_:32>> <= <<17:32,20:32>>] end,
+ "[foo || <<_:32>> <= <<17:32,20:32>>].",
+ [foo,foo]),
+
+ ?line check(fun() -> << <<X:32>> || X <- [1,2,3], X > 1 >> end,
+ "<< <<X:32>> || X <- [1,2,3], X > 1 >>.",
+ <<0,0,0,2,0,0,0,3>>),
+ ?line error_check("[X || <<X>> <= [a,b]].",{bad_generator,[a,b]}),
+ ok.
+
+otp_6787(doc) ->
+ ["OTP-6787. bitlevel binaries."];
+otp_6787(suite) ->
+ [];
+otp_6787(Config) when is_list(Config) ->
+ ?line check(
+ fun() -> <<16:(1024*1024)>> = <<16:(1024*1024)>> end,
+ "<<16:(1024*1024)>> = <<16:(1024*1024)>>.",
+ <<16:1048576>>),
+ ok.
+
+otp_6977(doc) ->
+ ["OTP-6977. ++ bug."];
+otp_6977(suite) ->
+ [];
+otp_6977(Config) when is_list(Config) ->
+ ?line check(
+ fun() -> (fun([$X] ++ _) -> ok end)("X") end,
+ "(fun([$X] ++ _) -> ok end)(\"X\").",
+ ok),
+ ok.
+
+otp_7550(doc) ->
+ ["OTP-7550. Support for UTF-8, UTF-16, UTF-32."];
+otp_7550(Config) when is_list(Config) ->
+
+ %% UTF-8.
+ ?line check(
+ fun() -> <<65>> = <<65/utf8>> end,
+ "<<65>> = <<65/utf8>>.",
+ <<65>>),
+ ?line check(
+ fun() -> <<350/utf8>> = <<197,158>> end,
+ "<<350/utf8>> = <<197,158>>.",
+ <<197,158>>),
+ ?line check(
+ fun() -> <<$b,$j,$\303,$\266,$r,$n>> = <<"bj\366rn"/utf8>> end,
+ "<<$b,$j,$\303,$\266,$r,$n>> = <<\"bj\366rn\"/utf8>>.",
+ <<$b,$j,$\303,$\266,$r,$n>>),
+
+ %% UTF-16.
+ ?line check(
+ fun() -> <<0,65>> = <<65/utf16>> end,
+ "<<0,65>> = <<65/utf16>>.",
+ <<0,65>>),
+ ?line check(
+ fun() -> <<16#D8,16#08,16#DF,16#45>> = <<16#12345/utf16>> end,
+ "<<16#D8,16#08,16#DF,16#45>> = <<16#12345/utf16>>.",
+ <<16#D8,16#08,16#DF,16#45>>),
+ ?line check(
+ fun() -> <<16#08,16#D8,16#45,16#DF>> = <<16#12345/little-utf16>> end,
+ "<<16#08,16#D8,16#45,16#DF>> = <<16#12345/little-utf16>>.",
+ <<16#08,16#D8,16#45,16#DF>>),
+
+ ?line check(
+ fun() -> <<350/utf16>> = <<1,94>> end,
+ "<<350/utf16>> = <<1,94>>.",
+ <<1,94>>),
+ ?line check(
+ fun() -> <<350/little-utf16>> = <<94,1>> end,
+ "<<350/little-utf16>> = <<94,1>>.",
+ <<94,1>>),
+ ?line check(
+ fun() -> <<16#12345/utf16>> = <<16#D8,16#08,16#DF,16#45>> end,
+ "<<16#12345/utf16>> = <<16#D8,16#08,16#DF,16#45>>.",
+ <<16#D8,16#08,16#DF,16#45>>),
+ ?line check(
+ fun() -> <<16#12345/little-utf16>> = <<16#08,16#D8,16#45,16#DF>> end,
+ "<<16#12345/little-utf16>> = <<16#08,16#D8,16#45,16#DF>>.",
+ <<16#08,16#D8,16#45,16#DF>>),
+
+ %% UTF-32.
+ ?line check(
+ fun() -> <<16#12345/utf32>> = <<16#0,16#01,16#23,16#45>> end,
+ "<<16#12345/utf32>> = <<16#0,16#01,16#23,16#45>>.",
+ <<16#0,16#01,16#23,16#45>>),
+ ?line check(
+ fun() -> <<16#0,16#01,16#23,16#45>> = <<16#12345/utf32>> end,
+ "<<16#0,16#01,16#23,16#45>> = <<16#12345/utf32>>.",
+ <<16#0,16#01,16#23,16#45>>),
+ ?line check(
+ fun() -> <<16#12345/little-utf32>> = <<16#45,16#23,16#01,16#00>> end,
+ "<<16#12345/little-utf32>> = <<16#45,16#23,16#01,16#00>>.",
+ <<16#45,16#23,16#01,16#00>>),
+ ?line check(
+ fun() -> <<16#12345/little-utf32>> end,
+ "<<16#12345/little-utf32>>.",
+ <<16#45,16#23,16#01,16#00>>),
+
+ %% Mixed.
+ ?line check(
+ fun() -> <<16#41,16#12345/utf32,16#0391:16,16#2E:8>> end,
+ "<<16#41,16#12345/utf32,16#0391:16,16#2E:8>>.",
+ <<16#41,16#00,16#01,16#23,16#45,16#03,16#91,16#2E>>),
+ ok.
+
+
+otp_8133(doc) ->
+ ["OTP-8133. Bit comprehension bug."];
+otp_8133(suite) ->
+ [];
+otp_8133(Config) when is_list(Config) ->
+ ?line check(
+ fun() ->
+ E = fun(N) ->
+ if
+ is_integer(N) -> <<N/integer>>;
+ true -> throw(foo)
+ end
+ end,
+ try << << (E(V))/binary >> || V <- [1,2,3,a] >>
+ catch foo -> ok
+ end
+ end,
+ "begin
+ E = fun(N) ->
+ if is_integer(N) -> <<N/integer>>;
+ true -> throw(foo)
+ end
+ end,
+ try << << (E(V))/binary >> || V <- [1,2,3,a] >>
+ catch foo -> ok
+ end
+ end.",
+ ok),
+ ?line check(
+ fun() ->
+ E = fun(N) ->
+ if
+ is_integer(N) -> <<N/integer>>;
+ true -> erlang:error(foo)
+ end
+ end,
+ try << << (E(V))/binary >> || V <- [1,2,3,a] >>
+ catch error:foo -> ok
+ end
+ end,
+ "begin
+ E = fun(N) ->
+ if is_integer(N) -> <<N/integer>>;
+ true -> erlang:error(foo)
+ end
+ end,
+ try << << (E(V))/binary >> || V <- [1,2,3,a] >>
+ catch error:foo -> ok
+ end
+ end.",
+ ok),
+ ok.
+
+funs(doc) ->
+ ["Simple cases, just to cover some code."];
+funs(suite) ->
+ [];
+funs(Config) when is_list(Config) ->
+ do_funs(none, none),
+ do_funs(lfh(), none),
+ do_funs(lfh(), efh()),
+
+ ?line error_check("nix:foo().", {access_not_allowed,nix}, lfh(), efh()),
+ ?line error_check("bar().", undef, none, none),
+
+ ?line check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end,
+ F1(F1, 1000) end,
+ "begin F1 = fun(F,N) -> count_down(F, N) end,"
+ "F1(F1,1000) end.",
+ 0, ['F1'], lfh(), none),
+
+ ?line check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end,
+ F1(F1, 1000) end,
+ "begin F1 = fun(F,N) -> count_down(F, N) end,"
+ "F1(F1,1000) end.",
+ 0, ['F1'], lfh_value(), none),
+
+ ?line check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end,
+ F1(F1, 1000) end,
+ "begin F1 = fun(F,N) -> count_down(F, N) end,"
+ "F1(F1,1000) end.",
+ 0, ['F1'], lfh_value_extra(), none),
+
+ ?line check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end,
+ F1(F1, 1000) end,
+ "begin F1 = fun(F,N) -> count_down(F, N) end,"
+ "F1(F1,1000) end.",
+ 0, ['F1'], {?MODULE,local_func_value}, none),
+ %% This is not documented, and only for backward compatibility (good!).
+ B0 = erl_eval:new_bindings(),
+ ?line check(fun() -> is_function(?MODULE:count_down_fun()) end,
+ "begin is_function(count_down_fun()) end.",
+ true, [], {?MODULE,local_func,[B0]},none),
+
+ EF = fun({timer,sleep}, As) when length(As) == 1 -> exit({got_it,sleep});
+ ({M,F}, As) -> apply(M, F, As)
+ end,
+ EFH = {value, EF},
+ ?line error_check("apply(timer, sleep, [1]).", got_it, none, EFH),
+ ?line error_check("begin F = fun(T) -> timer:sleep(T) end,F(1) end.",
+ got_it, none, EFH),
+ ?line error_check("fun c/1.", undef),
+ ?line error_check("fun a:b/0().", undef),
+
+ MaxArgs = 20,
+ ?line [true] =
+ lists:usort([run_many_args(SAs) || SAs <- many_args(MaxArgs)]),
+ ?line {'EXIT',{{argument_limit,_},_}} =
+ (catch run_many_args(many_args1(MaxArgs+1))),
+ ok.
+
+run_many_args({S, As}) ->
+ apply(eval_string(S), As) =:= As.
+
+many_args(N) ->
+ [many_args1(I) || I <- lists:seq(1, N)].
+
+many_args1(N) ->
+ F = fun(L, P) ->
+ tl(lists:flatten([","++P++integer_to_list(E) || E <- L]))
+ end,
+ L = lists:seq(1, N),
+ T = F(L, "V"),
+ S = lists:flatten(io_lib:format("fun(~s) -> [~s] end.", [T, T])),
+ {S, L}.
+
+do_funs(LFH, EFH) ->
+ %% LFH is not really used by these examples...
+
+ %% These tests do not prove that tail recursive functions really
+ %% work (that the process does not grow); one should also run them
+ %% manually with 1000 replaced by 1000000.
+
+ M = atom_to_list(?MODULE),
+ ?line check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end,
+ F1(F1, 1000) end,
+ concat(["begin F1 = fun(F,N) -> ", M,
+ ":count_down(F, N) end, F1(F1,1000) end."]),
+ 0, ['F1'], LFH, EFH),
+ ?line check(fun() -> F1 = fun(F,N) -> apply(?MODULE,count_down,[F,N])
+ end, F1(F1, 1000) end,
+ concat(["begin F1 = fun(F,N) -> apply(", M,
+ ",count_down,[F, N]) end, F1(F1,1000) end."]),
+ 0, ['F1'], LFH, EFH),
+ ?line check(fun() -> F1 = fun(F,N) -> {?MODULE,count_down}(F,N)
+ end, F1(F1, 1000) end,
+ concat(["begin F1 = fun(F,N) -> {", M,
+ ",count_down}(F, N) end, F1(F1,1000) end."]),
+ 0, ['F1'], LFH, EFH),
+ ?line check(fun() -> F = fun(F,N) when N > 0 -> apply(F,[F,N-1]);
+ (_F,0) -> ok end,
+ F(F, 1000)
+ end,
+ "begin F = fun(F,N) when N > 0 -> apply(F,[F,N-1]);"
+ "(_F,0) -> ok end,"
+ "F(F, 1000) end.",
+ ok, ['F'], LFH, EFH),
+ ?line check(fun() -> F = fun(F,N) when N > 0 ->
+ apply(erlang,apply,[F,[F,N-1]]);
+ (_F,0) -> ok end,
+ F(F, 1000)
+ end,
+ "begin F = fun(F,N) when N > 0 ->"
+ "apply(erlang,apply,[F,[F,N-1]]);"
+ "(_F,0) -> ok end,"
+ "F(F, 1000) end.",
+ ok, ['F'], LFH, EFH),
+ ?line check(fun() -> F = count_down_fun(),
+ SF = fun(SF, F1, N) -> F(SF, F1, N) end,
+ SF(SF, F, 1000) end,
+ concat(["begin F = ", M, ":count_down_fun(),"
+ "SF = fun(SF, F1, N) -> F(SF, F1, N) end,"
+ "SF(SF, F, 1000) end."]),
+ ok, ['F','SF'], LFH, EFH),
+
+
+ ?line check(fun() -> F = fun(X) -> A = 1+X, {X,A} end,
+ true = {2,3} == F(2) end,
+ "begin F = fun(X) -> A = 1+X, {X,A} end,
+ true = {2,3} == F(2) end.", true, ['F'], LFH, EFH),
+ ?line check(fun() -> F = fun(X) -> {erlang,'+'}(X,2) end,
+ true = 3 == F(1) end,
+ "begin F = fun(X) -> {erlang,'+'}(X,2) end,"
+ " true = 3 == F(1) end.", true, ['F'],
+ LFH, EFH),
+ ?line check(fun() -> F = fun(X) -> byte_size(X) end,
+ ?MODULE:do_apply(F,<<"hej">>) end,
+ concat(["begin F = fun(X) -> size(X) end,",
+ M,":do_apply(F,<<\"hej\">>) end."]),
+ 3, ['F'], LFH, EFH),
+
+ ?line check(fun() -> F1 = fun(X, Z) -> {X,Z} end,
+ Z = 5,
+ F2 = fun(X, Y) -> F1(Z,{X,Y}) end,
+ F3 = fun(X, Y) -> {a,F1(Z,{X,Y})} end,
+ {5,{x,y}} = F2(x,y),
+ {a,{5,{y,x}}} = F3(y,x),
+ {5,{5,y}} = F2(Z,y),
+ true = {5,{x,5}} == F2(x,Z) end,
+ "begin F1 = fun(X, Z) -> {X,Z} end,
+ Z = 5,
+ F2 = fun(X, Y) -> F1(Z,{X,Y}) end,
+ F3 = fun(X, Y) -> {a,F1(Z,{X,Y})} end,
+ {5,{x,y}} = F2(x,y),
+ {a,{5,{y,x}}} = F3(y,x),
+ {5,{5,y}} = F2(Z,y),
+ true = {5,{x,5}} == F2(x,Z) end.",
+ true, ['F1','Z','F2','F3'], LFH, EFH),
+ ?line check(fun() -> F = fun(X) -> byte_size(X) end,
+ F2 = fun(Y) -> F(Y) end,
+ ?MODULE:do_apply(F2,<<"hej">>) end,
+ concat(["begin F = fun(X) -> size(X) end,",
+ "F2 = fun(Y) -> F(Y) end,",
+ M,":do_apply(F2,<<\"hej\">>) end."]),
+ 3, ['F','F2'], LFH, EFH),
+ ?line check(fun() -> Z = 5, F = fun(X) -> {Z,X} end,
+ F2 = fun(Z) -> F(Z) end, F2(3) end,
+ "begin Z = 5, F = fun(X) -> {Z,X} end,
+ F2 = fun(Z) -> F(Z) end, F2(3) end.",
+ {5,3},['F','F2','Z'], LFH, EFH),
+ ?line check(fun() -> F = fun(Z) -> Z end,
+ F2 = fun(X) -> F(X), Z = {X,X}, Z end,
+ {1,1} = F2(1), Z = 7, Z end,
+ "begin F = fun(Z) -> Z end,
+ F2 = fun(X) -> F(X), Z = {X,X}, Z end,
+ {1,1} = F2(1), Z = 7, Z end.", 7, ['F','F2','Z'],
+ LFH, EFH),
+ ?line check(fun() -> F = fun(F, N) -> [?MODULE:count_down(F,N) || X <-[1]]
+ end, F(F,2) end,
+ concat(["begin F = fun(F, N) -> [", M,
+ ":count_down(F,N) || X <-[1]] end, F(F,2) end."]),
+ [[[0]]], ['F'], LFH, EFH),
+ ok.
+
+count_down(F, N) when N > 0 ->
+ F(F, N-1);
+count_down(_F, N) ->
+ N.
+
+count_down_fun() ->
+ fun(SF,F,N) when N > 0 -> SF(SF,F,N-1);
+ (_SF,_F,_N) -> ok
+ end.
+
+do_apply(F, V) ->
+ F(V).
+
+lfh() ->
+ {eval, fun(F, As, Bs) -> local_func(F, As, Bs) end}.
+
+local_func(F, As0, Bs0) when is_atom(F) ->
+ {As,Bs} = erl_eval:expr_list(As0, Bs0, {eval,lfh()}),
+ case erlang:function_exported(?MODULE, F, length(As)) of
+ true ->
+ {value,apply(?MODULE, F, As),Bs};
+ false ->
+ {value,apply(shell_default, F, As),Bs}
+ end.
+
+lfh_value_extra() ->
+ %% Not documented.
+ {value, fun(F, As) -> local_func_value(F, As) end, []}.
+
+lfh_value() ->
+ {value, fun(F, As) -> local_func_value(F, As) end}.
+
+local_func_value(F, As) when is_atom(F) ->
+ case erlang:function_exported(?MODULE, F, length(As)) of
+ true ->
+ apply(?MODULE, F, As);
+ false ->
+ apply(shell_default, F, As)
+ end.
+
+efh() ->
+ {value, fun(F, As) -> external_func(F, As) end}.
+
+external_func({M,_}, _As) when M == nix ->
+ exit({{access_not_allowed,M},[mfa]});
+external_func(F, As) when is_function(F) ->
+ apply(F, As);
+external_func({M,F}, As) ->
+ apply(M, F, As).
+
+
+
+try_catch(doc) ->
+ ["Test try-of-catch-after-end statement"];
+try_catch(suite) ->
+ [];
+try_catch(Config) when is_list(Config) ->
+ %% Match in of with catch
+ ?line check(fun() -> try 1 of 1 -> 2 catch _:_ -> 3 end end,
+ "try 1 of 1 -> 2 catch _:_ -> 3 end.", 2),
+ ?line check(fun() -> try 1 of 1 -> 2; 3 -> 4 catch _:_ -> 5 end end,
+ "try 1 of 1 -> 2; 3 -> 4 catch _:_ -> 5 end.", 2),
+ ?line check(fun() -> try 3 of 1 -> 2; 3 -> 4 catch _:_ -> 5 end end,
+ "try 3 of 1 -> 2; 3 -> 4 catch _:_ -> 5 end.", 4),
+ %% Just after
+ ?line check(fun () -> X = try 1 after put(try_catch, 2) end,
+ {X,get(try_catch)} end,
+ "begin X = try 1 after put(try_catch, 2) end, "
+ "{X,get(try_catch)} end.", {1,2}),
+ %% Match in of with after
+ ?line check(fun() -> X = try 1 of 1 -> 2 after put(try_catch, 3) end,
+ {X,get(try_catch)} end,
+ "begin X = try 1 of 1 -> 2 after put(try_catch, 3) end, "
+ "{X,get(try_catch)} end.", {2,3}),
+ ?line check(fun() -> X = try 1 of 1 -> 2; 3 -> 4
+ after put(try_catch, 5) end,
+ {X,get(try_catch)} end,
+ "begin X = try 1 of 1 -> 2; 3 -> 4 "
+ " after put(try_catch, 5) end, "
+ " {X,get(try_catch)} end.", {2,5}),
+ ?line check(fun() -> X = try 3 of 1 -> 2; 3 -> 4
+ after put(try_catch, 5) end,
+ {X,get(try_catch)} end,
+ "begin X = try 3 of 1 -> 2; 3 -> 4 "
+ " after put(try_catch, 5) end, "
+ " {X,get(try_catch)} end.", {4,5}),
+ %% Nomatch in of
+ ?line error_check("try 1 of 2 -> 3 catch _:_ -> 4 end.",
+ {try_clause,1}),
+ %% Nomatch in of with after
+ ?line check(fun () -> {'EXIT',{{try_clause,1},_}} =
+ begin catch try 1 of 2 -> 3
+ after put(try_catch, 4) end end,
+ get(try_catch) end,
+ "begin {'EXIT',{{try_clause,1},_}} = "
+ " begin catch try 1 of 2 -> 3 "
+ " after put(try_catch, 4) end end, "
+ " get(try_catch) end. ", 4),
+ %% Exception in try
+ ?line check(fun () -> try 1=2 catch error:{badmatch,2} -> 3 end end,
+ "try 1=2 catch error:{badmatch,2} -> 3 end.", 3),
+ ?line check(fun () -> try 1=2 of 3 -> 4
+ catch error:{badmatch,2} -> 5 end end,
+ "try 1=2 of 3 -> 4 "
+ "catch error:{badmatch,2} -> 5 end.", 5),
+ %% Exception in try with after
+ ?line check(fun () -> X = try 1=2
+ catch error:{badmatch,2} -> 3
+ after put(try_catch, 4) end,
+ {X,get(try_catch)} end,
+ "begin X = try 1=2 "
+ " catch error:{badmatch,2} -> 3 "
+ " after put(try_catch, 4) end, "
+ " {X,get(try_catch)} end. ", {3,4}),
+ ?line check(fun () -> X = try 1=2 of 3 -> 4
+ catch error:{badmatch,2} -> 5
+ after put(try_catch, 6) end,
+ {X,get(try_catch)} end,
+ "begin X = try 1=2 of 3 -> 4"
+ " catch error:{badmatch,2} -> 5 "
+ " after put(try_catch, 6) end, "
+ " {X,get(try_catch)} end. ", {5,6}),
+ %% Uncaught exception
+ ?line error_check("try 1=2 catch error:undefined -> 3 end. ",
+ {badmatch,2}),
+ ?line error_check("try 1=2 of 3 -> 4 catch error:undefined -> 5 end. ",
+ {badmatch,2}),
+ %% Uncaught exception with after
+ ?line check(fun () -> {'EXIT',{{badmatch,2},_}} =
+ begin catch try 1=2
+ after put(try_catch, 3) end end,
+ get(try_catch) end,
+ "begin {'EXIT',{{badmatch,2},_}} = "
+ " begin catch try 1=2 "
+ " after put(try_catch, 3) end end, "
+ " get(try_catch) end. ", 3),
+ ?line check(fun () -> {'EXIT',{{badmatch,2},_}} =
+ begin catch try 1=2 of 3 -> 4
+ after put(try_catch, 5) end end,
+ get(try_catch) end,
+ "begin {'EXIT',{{badmatch,2},_}} = "
+ " begin catch try 1=2 of 3 -> 4"
+ " after put(try_catch, 5) end end, "
+ " get(try_catch) end. ", 5),
+ ?line check(fun () -> {'EXIT',{{badmatch,2},_}} =
+ begin catch try 1=2 catch error:undefined -> 3
+ after put(try_catch, 4) end end,
+ get(try_catch) end,
+ "begin {'EXIT',{{badmatch,2},_}} = "
+ " begin catch try 1=2 catch error:undefined -> 3 "
+ " after put(try_catch, 4) end end, "
+ " get(try_catch) end. ", 4),
+ ?line check(fun () -> {'EXIT',{{badmatch,2},_}} =
+ begin catch try 1=2 of 3 -> 4
+ catch error:undefined -> 5
+ after put(try_catch, 6) end end,
+ get(try_catch) end,
+ "begin {'EXIT',{{badmatch,2},_}} = "
+ " begin catch try 1=2 of 3 -> 4 "
+ " catch error:undefined -> 5 "
+ " after put(try_catch, 6) end end, "
+ " get(try_catch) end. ", 6),
+ ok.
+
+
+eval_expr_5(doc) ->
+ ["(OTP-7933)"];
+eval_expr_5(suite) ->
+ [];
+eval_expr_5(Config) when is_list(Config) ->
+ ?line {ok,Tokens ,_} =
+ erl_scan:string("if a+4 == 4 -> yes; true -> no end. "),
+ ?line {ok, [Expr]} = erl_parse:parse_exprs(Tokens),
+ ?line {value, no, []} = erl_eval:expr(Expr, [], none, none, none),
+ ?line no = erl_eval:expr(Expr, [], none, none, value),
+ try
+ erl_eval:expr(Expr, [], none, none, 4711),
+ ?line function_clause = should_never_reach_here
+ catch
+ error:function_clause ->
+ ok
+ end.
+
+%% Check the string in different contexts: as is; in fun; from compiled code.
+check(F, String, Result) ->
+ check1(F, String, Result),
+ FunString = concat(["fun() -> ", no_final_dot(String), " end(). "]),
+ check1(F, FunString, Result),
+ CompileString = concat(["hd(lists:map(fun(_) -> ", no_final_dot(String),
+ " end, [foo])). "]),
+ check1(F, CompileString, Result).
+
+check1(F, String, Result) ->
+ Result = F(),
+ case catch parse_and_run(String) of
+ {value, Result, _} ->
+ ok;
+ Other ->
+ test_server:fail({eval, Other, Result})
+ end.
+
+check(F, String, Result, BoundVars, LFH, EFH) ->
+ Result = F(),
+ case catch parse_and_run(String, LFH, EFH) of
+ {value, Result, Bs} ->
+ %% We just assume that Bs is an orddict...
+ Keys = orddict:fetch_keys(Bs),
+ case sort(BoundVars) == Keys of
+ true ->
+ ok;
+ false ->
+ test_server:fail({check, BoundVars, Keys})
+ end,
+ ok;
+ Other ->
+ test_server:fail({check, Other, Result})
+ end.
+
+error_check(String, Result) ->
+ case catch parse_and_run(String) of
+ {'EXIT', {Result,_}} ->
+ ok;
+ Other ->
+ test_server:fail({eval, Other, Result})
+ end.
+
+error_check(String, Result, LFH, EFH) ->
+ case catch parse_and_run(String, LFH, EFH) of
+ {'EXIT', {Result,_}} ->
+ ok;
+ Other ->
+ test_server:fail({eval, Other, Result})
+ end.
+
+eval_string(String) ->
+ {value, Result, _} = parse_and_run(String),
+ Result.
+
+parse_and_run(String) ->
+ {ok,Tokens,_} = erl_scan:string(String),
+ {ok, [Expr]} = erl_parse:parse_exprs(Tokens),
+ erl_eval:expr(Expr, []).
+
+parse_and_run(String, LFH, EFH) ->
+ {ok,Tokens,_} = erl_scan:string(String),
+ {ok, [Expr]} = erl_parse:parse_exprs(Tokens),
+ erl_eval:expr(Expr, [], LFH, EFH).
+
+no_final_dot(S) ->
+ case lists:reverse(S) of
+ " ." ++ R -> lists:reverse(R);
+ "." ++ R -> lists:reverse(R);
+ _ -> S
+ end.
diff --git a/lib/debugger/test/exception_SUITE.erl b/lib/debugger/test/exception_SUITE.erl
new file mode 100644
index 0000000000..a74a93fd22
--- /dev/null
+++ b/lib/debugger/test/exception_SUITE.erl
@@ -0,0 +1,256 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-module(exception_SUITE).
+
+-export([all/1,init_per_testcase/2,fin_per_testcase/2,init_all/1,finish_all/1,
+ badmatch/1,pending_errors/1,nil_arith/1]).
+
+-export([bad_guy/2]).
+
+-include("test_server.hrl").
+
+all(suite) ->
+ [{conf,init_all,cases(),finish_all}].
+
+cases() ->
+ [badmatch, pending_errors, nil_arith].
+
+-define(try_match(E),
+ catch ?MODULE:bar(),
+ {'EXIT', {{badmatch, nomatch}, _}} = (catch E = nomatch)).
+
+init_per_testcase(_Case, Config) ->
+ test_lib:interpret(?MODULE),
+ Dog = test_server:timetrap(?t:minutes(1)),
+ [{watchdog,Dog}|Config].
+
+fin_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+init_all(Config) when is_list(Config) ->
+ ?line test_lib:interpret(?MODULE),
+ ?line true = lists:member(?MODULE, int:interpreted()),
+ ok.
+
+finish_all(Config) when is_list(Config) ->
+ ok.
+
+badmatch(doc) -> "Test that deliberately bad matches are reported correctly.";
+badmatch(suite) -> [];
+badmatch(Config) when list(Config) ->
+ ?line ?try_match(a),
+ ?line ?try_match(42),
+ ?line ?try_match({a, b, c}),
+ ?line ?try_match([]),
+ ?line ?try_match(1.0),
+ ok.
+
+pending_errors(doc) ->
+ ["Test various exceptions, in the presence of a previous error suppressed ",
+ "in a guard."];
+pending_errors(suite) -> [];
+pending_errors(Config) when list(Config) ->
+ ?line pending(e_badmatch, {badmatch, b}),
+ ?line pending(x, function_clause),
+ ?line pending(e_case, {case_clause, xxx}),
+ ?line pending(e_if, if_clause),
+ ?line pending(e_badarith, badarith),
+ ?line pending(e_undef, undef),
+ ?line pending(e_timeoutval, timeout_value),
+ ?line pending(e_badarg, badarg),
+ ?line pending(e_badarg_spawn, badarg),
+ ok.
+
+bad_guy(pe_badarith, Other) when Other+1 == 0 -> % badarith (suppressed)
+ ok;
+bad_guy(pe_badarg, Other) when length(Other) > 0 -> % badarg (suppressed)
+ ok;
+bad_guy(_, e_case) ->
+ case xxx of
+ ok -> ok
+ end; % case_clause
+bad_guy(_, e_if) ->
+ if
+ a == b -> ok
+ end; % if_clause
+bad_guy(_, e_badarith) ->
+ 1+b; % badarith
+bad_guy(_, e_undef) ->
+ non_existing_module:foo(); % undef
+bad_guy(_, e_timeoutval) ->
+ receive
+ after arne -> % timeout_value
+ ok
+ end;
+bad_guy(_, e_badarg) ->
+ node(xxx); % badarg
+bad_guy(_, e_badarg_spawn) ->
+ spawn({}, {}, {}); % badarg
+bad_guy(_, e_badmatch) ->
+ a = b. % badmatch
+
+pending(Arg, Expected) ->
+ pending(pe_badarith, Arg, Expected),
+ pending(pe_badarg, Arg, Expected).
+
+pending(First, Second, Expected) ->
+ pending_catched(First, Second, Expected),
+ pending_exit_message([First, Second], Expected).
+
+pending_catched(First, Second, Expected) ->
+ ok = io:format("Catching bad_guy(~p, ~p)", [First, Second]),
+ case catch bad_guy(First, Second) of
+ {'EXIT', Reason} ->
+ pending(Reason, bad_guy, [First, Second], Expected);
+ Other ->
+ test_server:fail({not_exit, Other})
+ end.
+
+pending_exit_message(Args, Expected) ->
+ ok = io:format("Trapping EXITs from spawn_link(~p, ~p, ~p)",
+ [?MODULE, bad_guy, Args]),
+ process_flag(trap_exit, true),
+ Pid = spawn_link(?MODULE, bad_guy, Args),
+ receive
+ {'EXIT', Pid, Reason} ->
+ pending(Reason, bad_guy, Args, Expected);
+ Other ->
+ test_server:fail({unexpected_message, Other})
+ after 10000 ->
+ test_server:fail(timeout)
+ end,
+ process_flag(trap_exit, false).
+
+pending({badarg,[{erlang,Bif,BifArgs},{?MODULE,Func,Arity}|_]}, Func, Args, _Code)
+ when atom(Bif), list(BifArgs), length(Args) == Arity -> %Threaded code.
+ ok;
+pending({badarg,[{erlang,Bif,BifArgs},{?MODULE,Func,Args}|_]}, Func, Args, _Code)
+ when atom(Bif), list(BifArgs) -> %From interpreted code.
+ ok;
+pending({undef,[{non_existing_module,foo,[]}|_]}, _, _, _) ->
+ ok;
+pending({function_clause,[{?MODULE,Func,Args}|_]}, Func, Args, _Code) ->
+ ok;
+pending({Code,[{?MODULE,Func,Arity}|_]}, Func, Args, Code) when length(Args) == Arity -> %Threaded code
+ ok;
+pending({Code,[{?MODULE,Func,Args}|_]}, Func, Args, Code) -> %From interpreted code.
+ ok;
+pending(Reason, Func, Args, Code) ->
+ test_server:fail({bad_exit_reason,Reason,{Func,Args,Code}}).
+
+nil_arith(doc) ->
+ "Test that doing arithmetics on [] gives a badarith EXIT and not a crash.";
+nil_arith(suite) ->
+ [];
+nil_arith(Config) when list(Config) ->
+ ?line ba_plus_minus_times([], []),
+
+ ?line ba_plus_minus_times([], 0),
+ ?line ba_plus_minus_times([], 42),
+ ?line ba_plus_minus_times([], 38724978123478923784),
+ ?line ba_plus_minus_times([], 38.72),
+
+ ?line ba_plus_minus_times(0, []),
+ ?line ba_plus_minus_times(334, []),
+ ?line ba_plus_minus_times(387249797813478923784, []),
+ ?line ba_plus_minus_times(344.22, []),
+
+ ?line ba_div_rem([], []),
+
+ ?line ba_div_rem([], 0),
+ ?line ba_div_rem([], 1),
+ ?line ba_div_rem([], 42),
+ ?line ba_div_rem([], 38724978123478923784),
+ ?line ba_div_rem(344.22, []),
+
+ ?line ba_div_rem(0, []),
+ ?line ba_div_rem(1, []),
+ ?line ba_div_rem(334, []),
+ ?line ba_div_rem(387249797813478923784, []),
+ ?line ba_div_rem(344.22, []),
+
+ ?line ba_div_rem(344.22, 0.0),
+ ?line ba_div_rem(1, 0.0),
+ ?line ba_div_rem(392873498733971, 0.0),
+
+ ?line ba_bop([], []),
+ ?line ba_bop(0, []),
+ ?line ba_bop(42, []),
+ ?line ba_bop(-42342742987343, []),
+ ?line ba_bop(238.342, []),
+ ?line ba_bop([], 0),
+ ?line ba_bop([], -243),
+ ?line ba_bop([], 243),
+ ?line ba_bop([], 2438724982478933),
+ ?line ba_bop([], 3987.37),
+
+ ?line ba_bnot([]),
+ ?line ba_bnot(23.33),
+
+ ?line ba_shift([], []),
+ ?line ba_shift([], 0),
+ ?line ba_shift([], 4),
+ ?line ba_shift([], -4),
+ ?line ba_shift([], 2343333333333),
+ ?line ba_shift([], -333333333),
+ ?line ba_shift([], 234.00),
+ ?line ba_shift(23, []),
+ ?line ba_shift(0, []),
+ ?line ba_shift(-3433443433433323, []),
+ ?line ba_shift(433443433433323, []),
+ ?line ba_shift(343.93, []),
+ ok.
+
+ba_plus_minus_times(A, B) ->
+ io:format("~p + ~p", [A, B]),
+ {'EXIT', {badarith, _}} = (catch A + B),
+ io:format("~p - ~p", [A, B]),
+ {'EXIT', {badarith, _}} = (catch A - B),
+ io:format("~p * ~p", [A, B]),
+ {'EXIT', {badarith, _}} = (catch A * B).
+
+ba_div_rem(A, B) ->
+ io:format("~p / ~p", [A, B]),
+ {'EXIT', {badarith, _}} = (catch A / B),
+ io:format("~p div ~p", [A, B]),
+ {'EXIT', {badarith, _}} = (catch A div B),
+ io:format("~p rem ~p", [A, B]),
+ {'EXIT', {badarith, _}} = (catch A rem B).
+
+ba_bop(A, B) ->
+ io:format("~p band ~p", [A, B]),
+ {'EXIT', {badarith, _}} = (catch A band B),
+ io:format("~p bor ~p", [A, B]),
+ {'EXIT', {badarith, _}} = (catch A bor B),
+ io:format("~p bxor ~p", [A, B]),
+ {'EXIT', {badarith, _}} = (catch A bxor B).
+
+ba_shift(A, B) ->
+ io:format("~p bsl ~p", [A, B]),
+ {'EXIT', {badarith, _}} = (catch A bsl B),
+ io:format("~p bsr ~p", [A, B]),
+ {'EXIT', {badarith, _}} = (catch A bsr B).
+
+ba_bnot(A) ->
+ io:format("bnot ~p", [A]),
+ {'EXIT', {badarith, _}} = (catch bnot A).
diff --git a/lib/debugger/test/fun_SUITE.erl b/lib/debugger/test/fun_SUITE.erl
new file mode 100644
index 0000000000..721048b6b6
--- /dev/null
+++ b/lib/debugger/test/fun_SUITE.erl
@@ -0,0 +1,233 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-module(fun_SUITE).
+
+-export([all/1,
+ init_per_testcase/2,end_per_testcase/2,
+ init_all/1,finish_all/1,
+ good_call/1,bad_apply/1,bad_fun_call/1,badarity/1,
+ ext_badarity/1,otp_6061/1]).
+-export([nothing/0]).
+
+-include("test_server.hrl").
+
+all(suite) ->
+ [{conf,init_all,cases(),finish_all}].
+
+cases() ->
+ [good_call,bad_apply,bad_fun_call,badarity,ext_badarity,otp_6061].
+
+init_per_testcase(_Case, Config) ->
+ test_lib:interpret(?MODULE),
+ Dog = test_server:timetrap(?t:minutes(1)),
+ [{watchdog,Dog}|Config].
+
+end_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+init_all(Config) when is_list(Config) ->
+ ?line test_lib:interpret(?MODULE),
+ ?line true = lists:member(?MODULE, int:interpreted()),
+ ok.
+
+finish_all(Config) when is_list(Config) ->
+ ok.
+
+good_call(Config) when is_list(Config) ->
+ ?line F = fun() -> ok end,
+ ?line ok = F(),
+ ?line FF = fun ?MODULE:nothing/0,
+ ?line ok = FF(),
+ ok.
+
+bad_apply(doc) ->
+ "Test that the correct EXIT code is returned for all types of bad funs.";
+bad_apply(suite) -> [];
+bad_apply(Config) when is_list(Config) ->
+ ?line bad_apply_fc(42, [0]),
+ ?line bad_apply_fc(xx, [1]),
+ ?line bad_apply_fc({}, [2]),
+ ?line bad_apply_fc({1}, [3]),
+ ?line bad_apply_fc({1,2,3}, [4]),
+ ?line bad_apply_fc({1,2,3}, [5]),
+ ?line bad_apply_fc({1,2,3,4}, [6]),
+ ?line bad_apply_fc({1,2,3,4,5,6}, [7]),
+ ?line bad_apply_fc({1,2,3,4,5}, [8]),
+ ?line bad_apply_badarg({1,2}, [9]),
+ ok.
+
+bad_apply_fc(Fun, Args) ->
+ Res = (catch apply(Fun, Args)),
+ erlang:garbage_collect(),
+ erlang:yield(),
+ case Res of
+ {'EXIT',{{badfun,Fun},_Where}} ->
+ ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res]);
+ Other ->
+ ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res]),
+ ?t:fail({bad_result,Other})
+ end.
+
+bad_apply_badarg(Fun, Args) ->
+ Res = (catch apply(Fun, Args)),
+ erlang:garbage_collect(),
+ erlang:yield(),
+ case Res of
+ {'EXIT',{{badfun,Fun},_Where}} ->
+ ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res]);
+ Other ->
+ ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res]),
+ ?t:fail({bad_result, Other})
+ end.
+
+bad_fun_call(doc) ->
+ "Try directly calling bad funs.";
+bad_fun_call(suite) -> [];
+bad_fun_call(Config) when is_list(Config) ->
+ ?line bad_call_fc(42),
+ ?line bad_call_fc(xx),
+ ?line bad_call_fc({}),
+ ?line bad_call_fc({1}),
+ ?line bad_call_fc({1,2,3}),
+ ?line bad_call_fc({1,2,3}),
+ ?line bad_call_fc({1,2,3,4}),
+ ?line bad_call_fc({1,2,3,4,5,6}),
+ ?line bad_call_fc({1,2,3,4,5}),
+ ?line bad_call_fc({1,2}),
+ ok.
+
+bad_call_fc(Fun) ->
+ Args = [some,stupid,args],
+ Res = (catch Fun(Args)),
+ case Res of
+ {'EXIT',{{badfun,Fun},_Where}} ->
+ ok = io:format("~p(~p) -> ~p\n", [Fun,Args,Res]);
+ Other ->
+ ok = io:format("~p(~p) -> ~p\n", [Fun,Args,Res]),
+ ?t:fail({bad_result,Other})
+ end.
+
+%% Call and apply valid external funs with wrong number of arguments.
+
+badarity(Config) when is_list(Config) ->
+ ?line Fun = fun() -> ok end,
+ ?line Stupid = {stupid,arguments},
+ ?line Args = [some,{stupid,arguments},here],
+
+ %% Simple call.
+
+ ?line Res = (catch Fun(some, Stupid, here)),
+ erlang:garbage_collect(),
+ erlang:yield(),
+ case Res of
+ {'EXIT',{{badarity,{Fun,Args}},[_|_]}} ->
+ ?line ok = io:format("~p(~p) -> ~p\n", [Fun,Args,Res]);
+ _ ->
+ ?line ok = io:format("~p(~p) -> ~p\n", [Fun,Args,Res]),
+ ?line ?t:fail({bad_result,Res})
+ end,
+
+ %% Apply.
+
+ ?line Res2 = (catch apply(Fun, Args)),
+ erlang:garbage_collect(),
+ erlang:yield(),
+ case Res2 of
+ {'EXIT',{{badarity,{Fun,Args}},[_|_]}} ->
+ ?line ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res2]);
+ _ ->
+ ?line ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res2]),
+ ?line ?t:fail({bad_result,Res2})
+ end,
+ ok.
+
+%% Call and apply valid external funs with wrong number of arguments.
+
+ext_badarity(Config) when is_list(Config) ->
+ ?line Fun = fun ?MODULE:nothing/0,
+ ?line Stupid = {stupid,arguments},
+ ?line Args = [some,{stupid,arguments},here],
+
+ %% Simple call.
+
+ ?line Res = (catch Fun(some, Stupid, here)),
+ erlang:garbage_collect(),
+ erlang:yield(),
+ case Res of
+ {'EXIT',{{badarity,{Fun,Args}},_}} ->
+ ?line ok = io:format("~p(~p) -> ~p\n", [Fun,Args,Res]);
+ _ ->
+ ?line ok = io:format("~p(~p) -> ~p\n", [Fun,Args,Res]),
+ ?line ?t:fail({bad_result,Res})
+ end,
+
+ %% Apply.
+
+ ?line Res2 = (catch apply(Fun, Args)),
+ erlang:garbage_collect(),
+ erlang:yield(),
+ case Res2 of
+ {'EXIT',{{badarity,{Fun,Args}},_}} ->
+ ?line ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res2]);
+ _ ->
+ ?line ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res2]),
+ ?line ?t:fail({bad_result,Res2})
+ end,
+ ok.
+
+nothing() ->
+ ok.
+
+otp_6061(suite) ->
+ [];
+otp_6061(doc) ->
+ ["Test handling of fun expression referring to uninterpreted code"];
+otp_6061(Config) when is_list(Config) ->
+
+ ?line OrigFlag = process_flag(trap_exit, true),
+
+ ?line Self = self(),
+ ?line Pid = spawn_link(fun() -> test_otp_6061(Self) end),
+
+ receive
+ working ->
+ ?line ok;
+ not_working ->
+ ?line ?t:fail(not_working);
+ {'EXIT', Pid, Reason} ->
+ ?line ?t:fail({crash, Reason})
+ after
+ 5000 ->
+ ?line ?t:fail(timeout)
+ end,
+
+ ?line process_flag(trap_exit, OrigFlag),
+
+ ok.
+
+test_otp_6061(Starter) ->
+ Passes = [2],
+ PassesF = [fun() -> Starter ! not_working end,
+ fun() -> Starter ! working end,
+ fun() -> Starter ! not_working end],
+ lists:foreach(fun(P)->(lists:nth(P,PassesF))() end,Passes).
diff --git a/lib/debugger/test/guard_SUITE.erl b/lib/debugger/test/guard_SUITE.erl
new file mode 100644
index 0000000000..b5269989c8
--- /dev/null
+++ b/lib/debugger/test/guard_SUITE.erl
@@ -0,0 +1,1479 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-module(guard_SUITE).
+
+-export([all/1,init_per_testcase/2,fin_per_testcase/2,init_all/1,finish_all/1,
+ bad_arith/1,bad_tuple/1,test_heap_guards/1,guard_bifs/1,
+ type_tests/1,const_guard/1,
+ const_cond/1,basic_not/1,complex_not/1,
+ semicolon/1,complex_semicolon/1,comma/1,
+ or_guard/1,more_or_guards/1,
+ complex_or_guards/1,and_guard/1,
+ xor_guard/1,more_xor_guards/1,
+ old_guard_tests/1,
+ build_in_guard/1,gbif/1,
+ t_is_boolean/1,is_function_2/1,
+ tricky/1,rel_ops/1,
+ basic_andalso_orelse/1,traverse_dcd/1,
+ check_qlc_hrl/1]).
+
+-include("test_server.hrl").
+
+-export([init/4]).
+-import(lists, [member/2]).
+
+all(suite) ->
+ [{conf,init_all,cases(),finish_all}].
+
+cases() ->
+ [bad_arith,bad_tuple,test_heap_guards,guard_bifs,type_tests,const_guard,
+ const_cond,basic_not,complex_not,
+ semicolon,complex_semicolon,
+ comma,or_guard,more_or_guards,
+ complex_or_guards,and_guard,
+ xor_guard,more_xor_guards,
+ build_in_guard,old_guard_tests,gbif,
+ t_is_boolean,is_function_2,tricky,rel_ops,
+ basic_andalso_orelse,traverse_dcd,check_qlc_hrl].
+
+init_per_testcase(_Case, Config) ->
+ test_lib:interpret(?MODULE),
+ ?line Dog = test_server:timetrap(?t:minutes(1)),
+ [{watchdog,Dog}|Config].
+
+fin_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+init_all(Config) when is_list(Config) ->
+ ?line test_lib:interpret(?MODULE),
+ ?line true = lists:member(?MODULE, int:interpreted()),
+ ok.
+
+finish_all(Config) when is_list(Config) ->
+ ok.
+
+bad_arith(doc) -> "Test that a bad arithmetic operation in a guard works correctly.";
+bad_arith(suite) -> [];
+bad_arith(Config) when list(Config) ->
+ ?line 5 = bad_arith1(2, 3),
+ ?line 10 = bad_arith1(1, infinity),
+ ?line 10 = bad_arith1(infinity, 1),
+ ?line 42 = bad_div(24, 0),
+ ok.
+
+bad_arith1(T1, T2) when T1+T2 < 10 ->
+ T1+T2;
+bad_arith1(_, _) ->
+ 10.
+
+bad_div(A, B) when A/B > 0 ->
+ A/B;
+bad_div(A, B) when A div B > 0 ->
+ A div B;
+bad_div(_A, _B) ->
+ 42.
+
+bad_tuple(doc) -> "Test that bad arguments to element/2 are handled correctly.";
+bad_tuple(suite) -> [];
+bad_tuple(Config) when list(Config) ->
+ ?line error = bad_tuple1(a),
+ ?line error = bad_tuple1({a, b}),
+ ?line x = bad_tuple1({x, b}),
+ ?line y = bad_tuple1({a, b, y}),
+ ok.
+
+bad_tuple1(T) when element(1, T) == x -> x;
+bad_tuple1(T) when element(3, T) == y -> y;
+bad_tuple1(_) -> error.
+
+test_heap_guards(doc) -> "";
+test_heap_guards(suite) -> [];
+test_heap_guards(Config) when list(Config) ->
+ ?line process_flag(trap_exit, true),
+ ?line Tuple = {a, tuple, is, built, here, xxx},
+ ?line List = [a, list, is, built, here],
+
+ ?line try_fun(fun a_case/1, [Tuple], [Tuple]),
+ ?line try_fun(fun a_case/1, [List], [List, List]),
+ ?line try_fun(fun a_case/1, [a], [a]),
+
+ ?line try_fun(fun an_if/1, [Tuple], [Tuple]),
+ ?line try_fun(fun an_if/1, [List], [List, List]),
+ ?line try_fun(fun an_if/1, [a], [a]),
+
+ ?line try_fun(fun receive_test/1, [Tuple], [Tuple]),
+ ?line try_fun(fun receive_test/1, [List], [List, List]),
+ ?line try_fun(fun receive_test/1, [a], [a]),
+ ok.
+
+a_case(V) ->
+ case V of
+ T when T == {a, tuple, is, built, here, xxx} ->
+ [T];
+ L when L == [a, list, is, built, here] ->
+ [L, L];
+ a ->
+ [a]
+ end.
+
+an_if(V) ->
+ if
+ V == {a, tuple, is, built, here, xxx} ->
+ [V];
+ V == [a, list, is, built, here] ->
+ [V, V];
+ V == a ->
+ [a]
+ end.
+
+receive_test(V) ->
+ self() ! V,
+ a_receive().
+
+a_receive() ->
+ receive
+ T when T == {a, tuple, is, built, here, xxx} ->
+ [T];
+ L when L == [a, list, is, built, here] ->
+ [L, L];
+ a ->
+ [a]
+ end.
+
+try_fun(Fun, Args, Result) ->
+ try_fun(16, Fun, Args, Result, []).
+
+try_fun(0, _, _, _, _) ->
+ ok;
+try_fun(Iter, Fun, Args, Result, Filler) ->
+ Pid = spawn_link(?MODULE, init, [self(),Fun,Args,list_to_tuple(Filler)]),
+ receive
+ {'EXIT',Pid,{result,Result}} ->
+ ?line try_fun(Iter-1, Fun, Args, Result, [0|Filler]);
+ {'EXIT',Pid,{result,Other}} ->
+ ?line io:format("Expected ~p; got ~p~n", [Result,Other]),
+ ?line test_server:fail();
+ Other ->
+ ?line test_server:fail({unexpected_message,Other})
+ end.
+
+init(_ReplyTo, Fun, Args, Filler) ->
+ Result = {result, apply(Fun, Args)},
+ dummy(Filler),
+ io:format("~p: result = ~p\n", [?LINE,Result]),
+ exit(Result).
+
+dummy(_) ->
+ ok.
+
+guard_bifs(doc) -> "Test all guard bifs with nasty (but legal arguments).";
+guard_bifs(suite) -> [];
+guard_bifs(Config) when list(Config) ->
+ ?line Big = -237849247829874297658726487367328971246284736473821617265433,
+ ?line Float = 387924.874,
+
+ %% Succeding use of guard bifs.
+
+ ?line try_gbif('abs/1', Big, -Big),
+ ?line try_gbif('float/1', Big, float(Big)),
+ ?line try_gbif('trunc/1', Float, 387924.0),
+ ?line try_gbif('round/1', Float, 387925.0),
+ ?line try_gbif('length/1', [], 0),
+
+ ?line try_gbif('length/1', [a], 1),
+ ?line try_gbif('length/1', [a, b], 2),
+ ?line try_gbif('length/1', lists:seq(0, 31), 32),
+
+ ?line try_gbif('hd/1', [a], a),
+ ?line try_gbif('hd/1', [a, b], a),
+
+ ?line try_gbif('tl/1', [a], []),
+ ?line try_gbif('tl/1', [a, b], [b]),
+ ?line try_gbif('tl/1', [a, b, c], [b, c]),
+
+ ?line try_gbif('size/1', {}, 0),
+ ?line try_gbif('size/1', {a}, 1),
+ ?line try_gbif('size/1', {a, b}, 2),
+ ?line try_gbif('size/1', {a, b, c}, 3),
+ ?line try_gbif('size/1', list_to_binary([]), 0),
+ ?line try_gbif('size/1', list_to_binary([1]), 1),
+ ?line try_gbif('size/1', list_to_binary([1, 2]), 2),
+ ?line try_gbif('size/1', list_to_binary([1, 2, 3]), 3),
+
+ ?line try_gbif('element/2', {x}, {1, x}),
+ ?line try_gbif('element/2', {x, y}, {1, x}),
+ ?line try_gbif('element/2', {x, y}, {2, y}),
+
+ ?line try_gbif('self/0', 0, self()),
+ ?line try_gbif('node/0', 0, node()),
+ ?line try_gbif('node/1', self(), node()),
+
+ %% Failing use of guard bifs.
+
+ ?line try_fail_gbif('abs/1', Big, 1),
+ ?line try_fail_gbif('abs/1', [], 1),
+
+ ?line try_fail_gbif('float/1', Big, 42),
+ ?line try_fail_gbif('float/1', [], 42),
+
+ ?line try_fail_gbif('trunc/1', Float, 0.0),
+ ?line try_fail_gbif('trunc/1', [], 0.0),
+
+ ?line try_fail_gbif('round/1', Float, 1.0),
+ ?line try_fail_gbif('round/1', [], a),
+
+ ?line try_fail_gbif('length/1', [], 1),
+ ?line try_fail_gbif('length/1', [a], 0),
+ ?line try_fail_gbif('length/1', a, 0),
+ ?line try_fail_gbif('length/1', {a}, 0),
+
+ ?line try_fail_gbif('hd/1', [], 0),
+ ?line try_fail_gbif('hd/1', [a], x),
+ ?line try_fail_gbif('hd/1', x, x),
+
+ ?line try_fail_gbif('tl/1', [], 0),
+ ?line try_fail_gbif('tl/1', [a], x),
+ ?line try_fail_gbif('tl/1', x, x),
+
+ ?line try_fail_gbif('size/1', {}, 1),
+ ?line try_fail_gbif('size/1', [], 0),
+ ?line try_fail_gbif('size/1', [a], 1),
+
+ ?line try_fail_gbif('element/2', {}, {1, x}),
+ ?line try_fail_gbif('element/2', {x}, {1, y}),
+ ?line try_fail_gbif('element/2', [], {1, z}),
+
+ ?line try_fail_gbif('self/0', 0, list_to_pid("<0.0.0>")),
+ ?line try_fail_gbif('node/0', 0, xxxx),
+ ?line try_fail_gbif('node/1', self(), xxx),
+ ?line try_fail_gbif('node/1', yyy, xxx),
+ ok.
+
+try_gbif(Id, X, Y) ->
+ case guard_bif(Id, X, Y) of
+ {Id, X, Y} ->
+ io:format("guard_bif(~p, ~p, ~p) -- ok", [Id, X, Y]);
+ Other ->
+ ?line ok = io:format("guard_bif(~p, ~p, ~p) -- bad result: ~p\n",
+ [Id, X, Y, Other]),
+ ?line test_server:fail()
+ end.
+
+try_fail_gbif(Id, X, Y) ->
+ case catch guard_bif(Id, X, Y) of
+ {'EXIT', {function_clause,{?MODULE,guard_bif,[Id,X,Y]}}} -> %Jam
+ io:format("guard_bif(~p, ~p, ~p) -- ok", [Id,X,Y]);
+ {'EXIT', {function_clause,[{?MODULE,guard_bif,[Id,X,Y]}|_]}} -> %Beam
+ io:format("guard_bif(~p, ~p, ~p) -- ok", [Id,X,Y]);
+ Other ->
+ ?line ok = io:format("guard_bif(~p, ~p, ~p) -- bad result: ~p\n",
+ [Id, X, Y, Other]),
+ ?line test_server:fail()
+ end.
+
+guard_bif('abs/1', X, Y) when abs(X) == Y ->
+ {'abs/1', X, Y};
+guard_bif('float/1', X, Y) when float(X) == Y ->
+ {'float/1', X, Y};
+guard_bif('trunc/1', X, Y) when trunc(X) == Y ->
+ {'trunc/1', X, Y};
+guard_bif('round/1', X, Y) when round(X) == Y ->
+ {'round/1', X, Y};
+guard_bif('length/1', X, Y) when length(X) == Y ->
+ {'length/1', X, Y};
+guard_bif('hd/1', X, Y) when hd(X) == Y ->
+ {'hd/1', X, Y};
+guard_bif('tl/1', X, Y) when tl(X) == Y ->
+ {'tl/1', X, Y};
+guard_bif('size/1', X, Y) when size(X) == Y ->
+ {'size/1', X, Y};
+guard_bif('element/2', X, {Pos, Expected}) when element(Pos, X) == Expected ->
+ {'element/2', X, {Pos, Expected}};
+guard_bif('self/0', X, Y) when self() == Y ->
+ {'self/0', X, Y};
+guard_bif('node/0', X, Y) when node() == Y ->
+ {'node/0', X, Y};
+guard_bif('node/1', X, Y) when node(X) == Y ->
+ {'node/1', X, Y}.
+
+type_tests(doc) -> "Test the type tests.";
+type_tests(suite) -> [];
+type_tests(Config) when list(Config) ->
+ ?line Types = all_types(),
+ ?line Tests = type_test_desc(),
+ ?line put(errors, 0),
+ ?line put(violations, 0),
+ ?line type_tests(Tests, Types),
+ ?line case {get(errors), get(violations)} of
+ {0, 0} ->
+ ok;
+ {0, N} ->
+ {comment, integer_to_list(N) ++ " standard violation(s)"};
+ {Errors, Violations} ->
+ io:format("~p sub test(s) failed, ~p violation(s)",
+ [Errors, Violations]),
+ ?line test_server:fail()
+ end.
+
+type_tests([{Test, AllowedTypes}| T], AllTypes) ->
+ type_tests(Test, AllTypes, AllowedTypes),
+ type_tests(T, AllTypes);
+type_tests([], _) ->
+ ok.
+
+type_tests(Test, [Type|T], Allowed) ->
+ {TypeTag, Value} = Type,
+ case member(TypeTag, Allowed) of
+ true ->
+ case catch type_test(Test, Value) of
+ Test ->
+ ok;
+ _Other ->
+ io:format("Test ~p(~p) failed", [Test, Value]),
+ put(errors, get(errors) + 1)
+ end;
+ false ->
+ case catch type_test(Test, Value) of
+ {'EXIT', {function_clause, {?MODULE, type_test, [Test, Value]}}} ->
+ ok;
+ {'EXIT', {function_clause,[{?MODULE,type_test,[Test,Value]}|_]}} ->
+ ok;
+ {'EXIT',Other} ->
+ ?line test_server:fail({unexpected_error_reason,Other});
+ tuple when function(Value) ->
+ io:format("Standard violation: Test ~p(~p) should fail",
+ [Test, Value]),
+ put(violations, get(violations) + 1);
+ _Other ->
+ io:format("Test ~p(~p) succeeded (should fail)", [Test, Value]),
+ put(errors, get(errors) + 1)
+ end
+ end,
+ type_tests(Test, T, Allowed);
+type_tests(_, [], _) ->
+ ok.
+
+all_types() ->
+ [{small, 42},
+ {big, 392742928742947293873938792874019287447829874290742},
+ {float, 3.14156},
+ {nil, []},
+ {cons, [a]},
+ {tuple, {a, b}},
+ {atom, xxxx},
+ {ref, make_ref()},
+ {pid, self()},
+ {port, open_port({spawn, efile}, [])},
+ {function, fun(X) -> X+1, "" end},
+ {binary, list_to_binary([])}].
+
+type_test_desc() ->
+ [{integer, [small, big]},
+ {float, [float]},
+ {number, [small, big, float]},
+ {atom, [atom]},
+ {list, [cons, nil]},
+ {nonempty_list, [cons]},
+ {nil, [nil]},
+ {tuple, [tuple]},
+ {pid, [pid]},
+ {port, [port]},
+ {reference, [ref]},
+ {function, [function]}].
+
+type_test(integer, X) when integer(X) ->
+ integer;
+type_test(float, X) when float(X) ->
+ float;
+type_test(number, X) when number(X) ->
+ number;
+type_test(atom, X) when atom(X) ->
+ atom;
+type_test(list, X) when list(X) ->
+ list;
+type_test(nonempty_list, [_]) ->
+ nonempty_list;
+type_test(nil, []) ->
+ nil;
+type_test(tuple, X) when tuple(X) ->
+ tuple;
+type_test(pid, X) when pid(X) ->
+ pid;
+type_test(reference, X) when reference(X) ->
+ reference;
+type_test(port, X) when port(X) ->
+ port;
+type_test(binary, X) when binary(X) ->
+ binary;
+type_test(function, X) when function(X) ->
+ function.
+
+const_guard(Config) when is_list(Config) ->
+ ?line if
+ (0 == 0) and ((0 == 0) or (0 == 0)) ->
+ ok
+ end.
+
+
+const_cond(Config) when is_list(Config) ->
+ ?line ok = const_cond({}, 0),
+ ?line ok = const_cond({a}, 1),
+ ?line error = const_cond({a,b}, 3),
+ ?line error = const_cond({a}, 0),
+ ?line error = const_cond({a,b}, 1),
+ ok.
+
+const_cond(T, Sz) ->
+ case T of
+ _X when false -> never;
+ _X when tuple(T), eq == eq, size(T) == Sz -> ok;
+ _X when tuple(T), eq == leq, size(T) =< Sz -> ok;
+ _X -> error
+ end.
+
+basic_not(Config) when is_list(Config) ->
+ True = id(true),
+ False = id(false),
+ Glurf = id(glurf),
+ A = id(5),
+ B = id(37.5),
+ C = id(-1),
+ D = id(5),
+ ATuple = {False,True,Glurf},
+
+ ?line check(fun() -> if not false -> ok; true -> error end end, ok),
+ ?line check(fun() -> if not true -> ok; true -> error end end, error),
+ ?line check(fun() -> if not False -> ok; true -> error end end, ok),
+ ?line check(fun() -> if not True -> ok; true -> error end end, error),
+
+ ?line check(fun() -> if A > B -> gt; A < B -> lt; A == B -> eq end end, lt),
+ ?line check(fun() -> if A > C -> gt; A < C -> lt; A == C -> eq end end, gt),
+ ?line check(fun() -> if A > D -> gt; A < D -> lt; A == D -> eq end end, eq),
+
+ ?line check(fun() -> if not (7 > 453) -> le; not (7 < 453) -> ge;
+ not (7 == 453) -> ne; true -> eq end end, le),
+ ?line check(fun() -> if not (7 > -8) -> le; not (7 < -8) -> ge;
+ not (7 == -8) -> ne; true -> eq end end, ge),
+ ?line check(fun() -> if not (7 > 7) -> le; not (7 < 7) -> ge;
+ not (7 == 7) -> ne; true -> eq end end, le),
+
+ ?line check(fun() -> if not (A > B) -> le; not (A < B) -> ge;
+ not (A == B) -> ne; true -> eq end end, le),
+ ?line check(fun() -> if not (A > C) -> le; not (A < C) -> ge;
+ not (A == C) -> ne; true -> eq end end, ge),
+ ?line check(fun() -> if not (A > D) -> le; not (A < D) -> ge;
+ not (A == D) -> ne; true -> eq end end, le),
+
+ ?line check(fun() -> if not element(1, ATuple) -> ok; true -> error end end, ok),
+ ?line check(fun() -> if not element(2, ATuple) -> ok; true -> error end end, error),
+ ?line check(fun() -> if not element(3, ATuple) -> ok; true -> error end end, error),
+
+ ?line check(fun() -> if not glurf -> ok; true -> error end end, error),
+ ?line check(fun() -> if not Glurf -> ok; true -> error end end, error),
+
+ ok.
+
+complex_not(Config) when is_list(Config) ->
+ ATuple = id({false,true,gurka}),
+ ?line check(fun() -> if not(element(1, ATuple)) -> ok; true -> error end end, ok),
+ ?line check(fun() -> if not(element(2, ATuple)) -> ok; true -> error end end, error),
+
+ ?line check(fun() -> if not(element(3, ATuple) == gurka) -> ok;
+ true -> error end end, error),
+ ?line check(fun() -> if not(element(3, ATuple) =/= gurka) -> ok;
+ true -> error end end, ok),
+
+ ?line check(fun() -> if {a,not(element(2, ATuple))} == {a,false} -> ok;
+ true -> error end end, ok),
+ ?line check(fun() -> if {a,not(element(1, ATuple))} == {a,false} -> ok;
+ true -> error end end, error),
+
+ ?line check(fun() -> if not(element(1, ATuple) or element(3, ATuple)) -> ok;
+ true -> error end end, error),
+
+ %% orelse
+ ?line check(fun() -> if not(element(1, ATuple) orelse element(3, ATuple)) -> ok;
+ true -> error end end, error),
+
+ ok.
+
+semicolon(Config) when is_list(Config) ->
+
+ %% True/false combined using ';' (literal atoms).
+
+ ?line check(fun() -> if true; false -> ok end end, ok),
+ ?line check(fun() -> if false; true -> ok end end, ok),
+ ?line check(fun() -> if true; true -> ok end end, ok),
+ ?line check(fun() -> if false; false -> ok; true -> error end end, error),
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} = (catch if false; false -> ok end),
+ exit
+ end, exit),
+
+ %% True/false combined used ';'.
+
+ True = id(true),
+ False = id(false),
+
+ ?line check(fun() -> if True; False -> ok end end, ok),
+ ?line check(fun() -> if False; True -> ok end end, ok),
+ ?line check(fun() -> if True; True -> ok end end, ok),
+ ?line check(fun() -> if False; False -> ok; true -> error end end, error),
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} = (catch if False; False -> ok end),
+ exit
+ end, exit),
+
+ %% Combine true/false with a non-boolean value.
+ Glurf = id(glurf),
+
+
+ ?line check(fun() -> if True; Glurf -> ok end end, ok),
+ ?line check(fun() -> if Glurf; True -> ok end end, ok),
+ ?line check(fun() -> if Glurf; Glurf -> ok; true -> error end end, error),
+ ?line check(fun() -> if False; Glurf -> ok; true -> error end end, error),
+ ?line check(fun() -> if Glurf; False -> ok; true -> error end end, error),
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} = (catch if Glurf; Glurf -> ok end),
+ exit
+ end, exit),
+
+ %% Combine true/false with errors.
+
+ ATuple = id({false,true,gurka}),
+
+ ?line check(fun() -> if True; element(42, ATuple) -> ok end end, ok),
+ ?line check(fun() -> if element(42, ATuple); True -> ok end end, ok),
+ ?line check(fun() -> if element(42, ATuple); element(42, ATuple) -> ok;
+ true -> error end end, error),
+ ?line check(fun() -> if False; element(42, ATuple) -> ok;
+ true -> error end end, error),
+ ?line check(fun() -> if element(42, ATuple);
+ False -> ok; true -> error end end, error),
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} =
+ (catch if element(42, ATuple);
+ element(42, ATuple) -> ok end),
+ exit
+ end, exit),
+
+ ok.
+
+complex_semicolon(Config) when is_list(Config) ->
+ ?line ok = csemi1(int, {blurf}),
+ ?line ok = csemi1(string, {blurf}),
+ ?line ok = csemi1(float, [a]),
+ ?line error = csemi1(35, 42),
+
+ %% 2
+ ?line ok = csemi2({}, {a,b,c}),
+ ?line ok = csemi2({1,3.5}, {a,b,c}),
+ ?line ok = csemi2(dum, {a,b,c}),
+
+ ?line ok = csemi2({45,-19.3}, {}),
+ ?line ok = csemi2({45,-19.3}, {dum}),
+ ?line ok = csemi2({45,-19.3}, {dum,dum}),
+
+ ?line error = csemi2({45}, {dum}),
+ ?line error = csemi2([], {dum}),
+ ?line error = csemi2({dum}, []),
+ ?line error = csemi2([], []),
+
+ %% 3
+ ?line csemi3(fun csemi3a/4),
+ ?line csemi3(fun csemi3b/4),
+ ?line csemi3(fun csemi3c/4),
+
+ %% 4
+ ?line csemi4(fun csemi4a/4),
+ ?line csemi4(fun csemi4b/4),
+ ?line csemi4(fun csemi4c/4),
+ ?line csemi4(fun csemi4d/4),
+
+ %% 4, 'orelse' instead of 'or'
+ ?line csemi4_orelse(fun csemi4_orelse_a/4),
+ ?line csemi4_orelse(fun csemi4_orelse_b/4),
+ ?line csemi4_orelse(fun csemi4_orelse_c/4),
+ ?line csemi4_orelse(fun csemi4_orelse_d/4),
+
+ ok.
+
+csemi1(Type, Val) when is_list(Val), Type == float;
+ Type == int; Type == string -> ok;
+csemi1(_, _) -> error.
+
+csemi2(A, B) when size(A) > 1; size(B) > 2 -> ok;
+csemi2(_, _) -> error.
+
+csemi3(Csemi3) ->
+ ok = Csemi3({}, {a,b,c}, [0], [0]),
+ ok = Csemi3({1,3.5}, {a,b,c}, -1, -1),
+ ok = Csemi3(dum, {a,b,c}, 0.0, 0.0),
+ ok = Csemi3(dum, {c}, b, a),
+ ok = Csemi3(dum, <<1,2,3>>, 0.0, 0.0),
+ ok = Csemi3(<<3.5/float>>, {a,b,c}, -1, -1),
+
+ ok = Csemi3({45,-19.3}, {}, [], []),
+ ok = Csemi3({45,-19.3}, {dum}, 42, 42),
+ ok = Csemi3({45,-19.3}, {dum,dum}, 33, 33),
+
+ ok = Csemi3({45}, {dum}, 1.0, 0),
+ ok = Csemi3([a], {dum}, 1.0, 0),
+ ok = Csemi3({dum}, [], 1.0, 0),
+ ok = Csemi3([], [], 1.0, 0),
+ ok = Csemi3(blurf, {dum}, 1.0, 0),
+ ok = Csemi3({a}, blurf, 1.0, 0),
+ ok = Csemi3([a], [dum], 1.0, 0),
+ ok = Csemi3({dum}, [], 1.0, 0),
+ ok = Csemi3([], [], 1.0, 0),
+
+ error = Csemi3({45}, {dum}, 0, 0),
+ error = Csemi3([a], {dum}, 0, 0),
+ error = Csemi3({dum}, [], 0, 0),
+ error = Csemi3([], [], 0, 0),
+ ok.
+
+csemi3a(A, B, X, Y) when X > Y; size(A) > 1; size(B) > 2 -> ok;
+csemi3a(_, _, _, _) -> error.
+
+csemi3b(A, B, X, Y) when size(A) > 1; X > Y; size(B) > 2 -> ok;
+csemi3b(_, _, _, _) -> error.
+
+csemi3c(A, B, X, Y) when size(A) > 1; size(B) > 2; X > Y -> ok;
+csemi3c(_, _, _, _) -> error.
+
+
+csemi4(Test) ->
+ ok = Test({a,b}, 2, {c,d}, 2),
+ ok = Test({1,2,3}, 0, [], 0),
+ ok = Test({}, 2, blurf, 0),
+ ok = Test({}, 2, {1}, 2),
+
+ error = Test([], 4, {}, 0),
+ error = Test({}, 0, [a,b], 4),
+ error = Test({}, 0, [a,b], 0),
+ error = Test([], 0, {}, 0),
+ error = Test({}, 0, {}, 0),
+
+ ok.
+
+csemi4a(A, X, B, Y) when (size(A) > 1) or (X > 1);
+ (size(B) > 1) or (Y > 1) -> ok;
+csemi4a(_, _, _, _) -> error.
+
+csemi4b(A, X, B, Y) when (X > 1) or (size(A) > 1);
+ (size(B) > 1) or (Y > 1) -> ok;
+csemi4b(_, _, _, _) -> error.
+
+csemi4c(A, X, B, Y) when (size(A) > 1) or (X > 1);
+ (Y > 1) or (size(B) > 1) -> ok;
+csemi4c(_, _, _, _) -> error.
+
+csemi4d(A, X, B, Y) when (X > 1) or (size(A) > 1);
+ (Y > 1) or (size(B) > 1) -> ok;
+csemi4d(_, _, _, _) -> error.
+
+
+csemi4_orelse(Test) ->
+ ok = Test({a,b}, 2, {c,d}, 2),
+ ok = Test({1,2,3}, 0, [], 0),
+ ok = Test({}, 2, blurf, 0),
+ ok = Test({}, 2, {1}, 2),
+
+ ?line error = Test([], 1, {}, 0),
+
+ ok.
+
+csemi4_orelse_a(A, X, B, Y) when (size(A) > 1) orelse (X > 1);
+ (size(B) > 1) orelse (Y > 1) -> ok;
+csemi4_orelse_a(_, _, _, _) -> error.
+
+csemi4_orelse_b(A, X, B, Y) when (X > 1) orelse (size(A) > 1);
+ (size(B) > 1) orelse (Y > 1) -> ok;
+csemi4_orelse_b(_, _, _, _) -> error.
+
+csemi4_orelse_c(A, X, B, Y) when (size(A) > 1) orelse (X > 1);
+ (Y > 1) orelse (size(B) > 1) -> ok;
+csemi4_orelse_c(_, _, _, _) -> error.
+
+csemi4_orelse_d(A, X, B, Y) when (X > 1) or (size(A) > 1);
+ (Y > 1) or (size(B) > 1) -> ok;
+csemi4_orelse_d(_, _, _, _) -> error.
+
+
+comma(Config) when is_list(Config) ->
+
+ %% ',' combinations of literal true/false.
+
+ ?line check(fun() -> if true, false -> ok; true -> error end end, error),
+ ?line check(fun() -> if false, true -> ok; true -> error end end, error),
+ ?line check(fun() -> if true, true -> ok end end, ok),
+ ?line check(fun() -> if false, false -> ok; true -> error end end, error),
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} =
+ (catch if true, false -> ok;
+ false, true -> ok;
+ false, false -> ok
+ end),
+ exit
+ end, exit),
+
+ %% ',' combinations of true/false in variables.
+
+ True = id(true),
+ False = id(false),
+
+ ?line check(fun() -> if True, False -> ok; true -> error end end, error),
+ ?line check(fun() -> if False, True -> ok; true -> error end end, error),
+ ?line check(fun() -> if True, True -> ok end end, ok),
+ ?line check(fun() -> if False, False -> ok; true -> error end end, error),
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} =
+ (catch if True, False -> ok;
+ False, True -> ok;
+ False, False -> ok
+ end),
+ exit
+ end, exit),
+
+ %% ',' combinations of true/false, and non-boolean in variables.
+
+ Glurf = id(glurf),
+
+ ?line check(fun() -> if True, Glurf -> ok; true -> error end end, error),
+ ?line check(fun() -> if Glurf, True -> ok; true -> error end end, error),
+ ?line check(fun() -> if True, True -> ok end end, ok),
+ ?line check(fun() -> if Glurf, Glurf -> ok; true -> error end end, error),
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} =
+ (catch if True, Glurf -> ok;
+ Glurf, True -> ok;
+ Glurf, Glurf -> ok
+ end),
+ exit
+ end, exit),
+
+ %% ',' combinations of true/false with errors.
+ ATuple = id({a,b,c}),
+
+ ?line check(fun() -> if True, element(42, ATuple) -> ok;
+ true -> error end end, error),
+ ?line check(fun() -> if element(42, ATuple), True -> ok;
+ true -> error end end, error),
+ ?line check(fun() -> if True, True -> ok end end, ok),
+ ?line check(fun() -> if element(42, ATuple), element(42, ATuple) -> ok;
+ true -> error end end, error),
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} =
+ (catch if True, element(42, ATuple) -> ok;
+ element(42, ATuple), True -> ok;
+ element(42, ATuple), element(42, ATuple) -> ok
+ end),
+ exit
+ end, exit),
+
+ ok.
+
+or_guard(Config) when is_list(Config) ->
+ True = id(true),
+ False = id(false),
+ Glurf = id(glurf),
+
+ %% 'or' combinations of literal true/false.
+ ?line check(fun() -> if true or false -> ok end end, ok),
+ ?line check(fun() -> if false or true -> ok end end, ok),
+ ?line check(fun() -> if true or true -> ok end end, ok),
+ ?line check(fun() -> if false or false -> ok; true -> error end end, error),
+
+ ?line check(fun() -> if glurf or true -> ok; true -> error end end, error),
+ ?line check(fun() -> if true or glurf -> ok; true -> error end end, error),
+ ?line check(fun() -> if glurf or glurf -> ok; true -> error end end, error),
+
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} = (catch if false or false -> ok end),
+ exit
+ end, exit),
+
+
+ %% 'or' combinations using variables containing true/false.
+ ?line check(fun() -> if True or False -> ok end end, ok),
+ ?line check(fun() -> if False or True -> ok end end, ok),
+ ?line check(fun() -> if True or True -> ok end end, ok),
+ ?line check(fun() -> if False or False -> ok; true -> error end end, error),
+
+ ?line check(fun() -> if True or Glurf -> ok; true -> error end end, error),
+ ?line check(fun() -> if Glurf or True -> ok; true -> error end end, error),
+ ?line check(fun() -> if Glurf or Glurf -> ok; true -> error end end, error),
+
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} = (catch if False or False -> ok end),
+ exit
+ end, exit),
+
+ ok.
+
+more_or_guards(Config) when is_list(Config) ->
+ True = id(true),
+ False = id(false),
+ ATuple = id({false,true,gurka}),
+
+ ?line check(fun() ->
+ if element(42, ATuple) or False -> ok;
+ true -> error end
+ end, error),
+
+ ?line check(fun() ->
+ if False or element(42, ATuple) -> ok;
+ true -> error end
+ end, error),
+
+ ?line check(fun() ->
+ if element(18, ATuple) or element(42, ATuple) -> ok;
+ true -> error end
+ end, error),
+
+ ?line check(fun() ->
+ if True or element(42, ATuple) -> ok;
+ true -> error end
+ end, error),
+
+ ?line check(fun() ->
+ if element(42, ATuple) or True -> ok;
+ true -> error end
+ end, error),
+
+ ?line check(fun() ->
+ if element(1, ATuple) or element(42, ATuple) or True -> ok;
+ true -> error end
+ end, error),
+
+ ?line check(fun() ->
+ if element(1, ATuple) or True or element(42, ATuple) -> ok;
+ true -> error end
+ end, error),
+
+ ?line check(fun() ->
+ if
+ (<<False:8>> == <<0>>) or element(2, ATuple) -> ok;
+ true -> error end
+ end, error),
+
+ ?line check(fun() ->
+ if
+ element(2, ATuple) or (<<True:8>> == <<1>>) -> ok;
+ true -> error end
+ end, error),
+
+ ?line check(fun() ->
+ if element(2, ATuple) or element(42, ATuple) -> ok;
+ true -> error end
+ end, error),
+
+ ?line check(fun() ->
+ if
+ element(1, ATuple) or
+ element(2, ATuple) or
+ element(19, ATuple) -> ok;
+ true -> error end
+ end, error),
+ ok.
+
+complex_or_guards(Config) when is_list(Config) ->
+ %% complex_or_1/2
+ ?line ok = complex_or_1({a,b,c,d}, {1,2,3}),
+ ?line ok = complex_or_1({a,b,c,d}, {1}),
+ ?line ok = complex_or_1({a}, {1,2,3}),
+ ?line error = complex_or_1({a}, {1}),
+
+ ?line error = complex_or_1(1, 2),
+ ?line error = complex_or_1([], {a,b,c,d}),
+ ?line error = complex_or_1({a,b,c,d}, []),
+
+
+ %% complex_or_2/1
+ ?line ok = complex_or_2({true,{}}),
+ ?line ok = complex_or_2({false,{a}}),
+ ?line ok = complex_or_2({false,{a,b,c}}),
+ ?line ok = complex_or_2({true,{a,b,c,d}}),
+
+ ?line error = complex_or_2({blurf,{a,b,c}}),
+
+ ?line error = complex_or_2({true}),
+ ?line error = complex_or_2({true,no_tuple}),
+ ?line error = complex_or_2({true,[]}),
+
+ %% complex_or_3/2
+ ?line ok = complex_or_3({true}, {}),
+ ?line ok = complex_or_3({false}, {a}),
+ ?line ok = complex_or_3({false}, {a,b,c}),
+ ?line ok = complex_or_3({true}, {a,b,c,d}),
+ ?line ok = complex_or_3({false}, <<1,2,3>>),
+ ?line ok = complex_or_3({true}, <<1,2,3,4>>),
+
+ ?line error = complex_or_3(blurf, {a,b,c}),
+
+ ?line error = complex_or_3({false}, <<1,2,3,4>>),
+ ?line error = complex_or_3([], <<1,2>>),
+ ?line error = complex_or_3({true}, 45),
+ ?line error = complex_or_3(<<>>, <<>>),
+
+ %% complex_or_4/2
+ ?line ok = complex_or_4(<<1,2,3>>, {true}),
+ ?line ok = complex_or_4(<<1,2,3>>, {false}),
+ ?line ok = complex_or_4(<<1,2,3>>, {true}),
+ ?line ok = complex_or_4({1,2,3}, {true}),
+ ?line error = complex_or_4({1,2,3,4}, {false}),
+
+ ?line error = complex_or_4(<<1,2,3,4>>, []),
+ ?line error = complex_or_4([], {true}),
+
+ %% complex_or_5/2
+ ?line ok = complex_or_5(<<1>>, {false}),
+ ?line ok = complex_or_5(<<1,2,3>>, {true}),
+ ?line ok = complex_or_5(<<1,2,3,4>>, {false}),
+ ?line ok = complex_or_5({1,2,3}, {false}),
+ ?line ok = complex_or_5({1,2,3,4}, {false}),
+
+ ?line error = complex_or_5(blurf, {false}),
+ ?line error = complex_or_5(<<1>>, klarf),
+ ?line error = complex_or_5(blurf, klarf),
+
+ %% complex_or_6/2
+ ?line ok = complex_or_6({true,true}, {1,2,3,4}),
+ ?line ok = complex_or_6({true,true}, <<1,2,3,4>>),
+ ?line ok = complex_or_6({false,false}, <<1,2,3,4>>),
+ ?line ok = complex_or_6({false,true}, <<1>>),
+ ?line ok = complex_or_6({true,false}, {1}),
+ ?line ok = complex_or_6({true,true}, {1}),
+
+ ?line error = complex_or_6({false,false}, {1}),
+
+ ?line error = complex_or_6({true}, {1,2,3,4}),
+ ?line error = complex_or_6({}, {1,2,3,4}),
+ ?line error = complex_or_6([], {1,2,3,4}),
+ ?line error = complex_or_6([], {1,2,3,4}),
+ ?line error = complex_or_6({true,false}, klurf),
+
+ ok.
+
+complex_or_1(A, B) ->
+ if
+ ((3 < size(A)) and (size(A) < 9)) or
+ ((2 < size(B)) and (size(B) < 7)) -> ok;
+ true -> error
+ end.
+
+complex_or_2(Tuple) ->
+ if
+ element(1, Tuple) or not (size(element(2, Tuple)) > 3) -> ok;
+ true -> error
+ end.
+
+complex_or_3(A, B) ->
+ if
+ not (size(B) > 3) or element(1, A) -> ok;
+ true -> error
+ end.
+
+complex_or_4(A, B) ->
+ if
+ not (is_tuple(A) and (size(A) > 3)) or element(1, B) -> ok;
+ true -> error
+ end.
+
+complex_or_5(A, B) ->
+ if
+ not (is_tuple(A) or (size(A) > 3)) or not element(1, B) -> ok;
+ true -> error
+ end.
+
+complex_or_6(A, B) ->
+ if
+ not (not element(1, A) and not element(2, A)) or
+ not (not (size(B) > 3)) -> ok;
+ true -> error
+ end.
+
+and_guard(Config) when is_list(Config) ->
+
+ %% 'and' combinations of literal true/false.
+
+ ?line check(fun() -> if true and false -> ok; true -> error end end, error),
+ ?line check(fun() -> if false and true -> ok; true -> error end end, error),
+ ?line check(fun() -> if true and true -> ok end end, ok),
+ ?line check(fun() -> if false and false -> ok; true -> error end end, error),
+
+ ?line check(fun() -> if glurf and true -> ok; true -> error end end, error),
+ ?line check(fun() -> if true and glurf -> ok; true -> error end end, error),
+ ?line check(fun() -> if glurf and glurf -> ok; true -> error end end, error),
+
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} =
+ (catch if true and false -> ok;
+ false and true -> ok;
+ false and false -> ok
+ end),
+ exit
+ end, exit),
+
+ %% 'and' combinations of true/false in variables.
+
+ True = id(true),
+ False = id(false),
+
+ ?line check(fun() -> if True and False -> ok; true -> error end end, error),
+ ?line check(fun() -> if False and True -> ok; true -> error end end, error),
+ ?line check(fun() -> if True and True -> ok end end, ok),
+ ?line check(fun() -> if False and False -> ok; true -> error end end, error),
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} =
+ (catch if True and False -> ok;
+ False and True -> ok;
+ False and False -> ok
+ end),
+ exit
+ end, exit),
+
+ %% 'and' combinations of true/false and a non-boolean in variables.
+
+ Glurf = id(glurf),
+
+ ?line check(fun() -> if True and Glurf -> ok; true -> error end end, error),
+ ?line check(fun() -> if Glurf and True -> ok; true -> error end end, error),
+ ?line check(fun() -> if True and True -> ok end end, ok),
+ ?line check(fun() -> if Glurf and Glurf -> ok; true -> error end end, error),
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} =
+ (catch if True and Glurf -> ok;
+ Glurf and True -> ok;
+ Glurf and Glurf -> ok
+ end),
+ exit
+ end, exit),
+
+ %% 'and' combinations of true/false with errors.
+ ATuple = id({a,b,c}),
+
+ ?line check(fun() -> if True and element(42, ATuple) -> ok;
+ true -> error end end, error),
+ ?line check(fun() -> if element(42, ATuple) and True -> ok;
+ true -> error end end, error),
+ ?line check(fun() -> if True and True -> ok end end, ok),
+ ?line check(fun() -> if element(42, ATuple) and element(42, ATuple) -> ok;
+ true -> error end end, error),
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} =
+ (catch if True and element(42, ATuple) -> ok;
+ element(42, ATuple) and True -> ok;
+ element(42, ATuple) and element(42, ATuple) -> ok
+ end),
+ exit
+ end, exit),
+
+ ?line ok = relprod({'Set',a,b}, {'Set',a,b}),
+
+ ok.
+
+relprod(R1, R2) when (erlang:size(R1) =:= 3) and (erlang:element(1,R1) =:= 'Set'), (erlang:size(R2) =:= 3) and (erlang:element(1,R2) =:= 'Set') ->
+ ok.
+
+
+xor_guard(Config) when is_list(Config) ->
+
+ %% 'xor' combinations of literal true/false.
+ ?line check(fun() -> if true xor false -> ok end end, ok),
+ ?line check(fun() -> if false xor true -> ok end end, ok),
+ ?line check(fun() -> if true xor true -> ok; true -> error end end, error),
+ ?line check(fun() -> if false xor false -> ok; true -> error end end, error),
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} = (catch if false xor false -> ok end),
+ exit
+ end, exit),
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} = (catch if true xor true -> ok end),
+ exit
+ end, exit),
+
+
+ %% 'xor' combinations using variables containing true/false.
+
+ True = id(true),
+ False = id(false),
+
+ ?line check(fun() -> if True xor False -> ok end end, ok),
+ ?line check(fun() -> if False xor True -> ok end end, ok),
+ ?line check(fun() -> if True xor True -> ok; true -> error end end, error),
+ ?line check(fun() -> if False xor False -> ok; true -> error end end, error),
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} = (catch if False xor False -> ok end),
+ exit
+ end, exit),
+ ?line check(fun() ->
+ {'EXIT',{if_clause,_}} = (catch if True xor True -> ok end),
+ exit
+ end, exit),
+
+ ok.
+
+more_xor_guards(Config) when is_list(Config) ->
+ True = id(true),
+ False = id(false),
+ ATuple = id({false,true,gurka}),
+
+ ?line check(fun() ->
+ if element(42, ATuple) xor False -> ok;
+ true -> error end
+ end, error),
+
+ ?line check(fun() ->
+ if False xor element(42, ATuple) xor False -> ok;
+ true -> error end
+ end, error),
+
+ ?line check(fun() ->
+ if element(18, ATuple) xor element(42, ATuple) -> ok;
+ true -> error end
+ end, error),
+
+ ?line check(fun() ->
+ if True xor element(42, ATuple) -> ok;
+ true -> error end
+ end, error),
+
+ ?line check(fun() ->
+ if element(42, ATuple) xor True -> ok;
+ true -> error end
+ end, error),
+ ok.
+
+build_in_guard(Config) when is_list(Config) ->
+ SubBin = <<5.0/float>>,
+ ?line B = <<1,SubBin/binary,3.5/float>>,
+ ?line if
+ B =:= <<1,SubBin/binary,3.5/float>> -> ok
+ end.
+
+old_guard_tests(Config) when list(Config) ->
+ %% Check that all the old guard tests are still recognized.
+ ?line list = og(Config),
+ ?line atom = og(an_atom),
+ ?line binary = og(<<1,2>>),
+ ?line float = og(3.14),
+ ?line integer = og(43),
+ ?line a_function = og(fun() -> ok end),
+ ?line pid = og(self()),
+ ?line reference = og(make_ref()),
+ ?line tuple = og({}),
+
+ ?line number = on(45.333),
+ ?line number = on(-19),
+ ok.
+
+og(V) when atom(V) -> atom;
+og(V) when binary(V) -> binary;
+og(V) when float(V) -> float;
+og(V) when integer(V) -> integer;
+og(V) when function(V) -> a_function;
+og(V) when list(V) -> list;
+og(V) when pid(V) -> pid;
+og(V) when port(V) -> port;
+og(V) when reference(V) -> reference;
+og(V) when tuple(V) -> tuple;
+og(_) -> what.
+
+on(V) when number(V) -> number;
+on(_) -> not_number.
+
+gbif(Config) when is_list(Config) ->
+ ?line error = gbif_1(1, {false,true}),
+ ?line ok = gbif_1(2, {false,true}),
+ ok.
+
+gbif_1(P, T) when element(P, T) -> ok;
+gbif_1(_, _) -> error.
+
+
+t_is_boolean(Config) when is_list(Config) ->
+ ?line true = is_boolean(true),
+ ?line true = is_boolean(false),
+ ?line true = is_boolean(id(true)),
+ ?line true = is_boolean(id(false)),
+
+ ?line false = is_boolean(glurf),
+ ?line false = is_boolean(id(glurf)),
+
+ ?line false = is_boolean([]),
+ ?line false = is_boolean(id([])),
+ ?line false = is_boolean(42),
+ ?line false = is_boolean(id(-42)),
+
+ ?line false = is_boolean(math:pi()),
+ ?line false = is_boolean(384793478934378924978439789873478934897),
+
+ ?line false = is_boolean(id(self())),
+ ?line false = is_boolean(id({x,y,z})),
+ ?line false = is_boolean(id([a,b,c])),
+ ?line false = is_boolean(id(make_ref())),
+ ?line false = is_boolean(id(<<1,2,3>>)),
+
+ ?line ok = bool(true),
+ ?line ok = bool(false),
+ ?line ok = bool(id(true)),
+ ?line ok = bool(id(false)),
+
+ ?line error = bool(glurf),
+ ?line error = bool(id(glurf)),
+
+ ?line error = bool([]),
+ ?line error = bool(id([])),
+ ?line error = bool(42),
+ ?line error = bool(id(-42)),
+
+ ?line error = bool(math:pi()),
+ ?line error = bool(384793478934378924978439789873478934897),
+
+ ?line error = bool(id(self())),
+ ?line error = bool(id({x,y,z})),
+ ?line error = bool(id([a,b,c])),
+ ?line error = bool(id(make_ref())),
+ ?line error = bool(id(<<1,2,3>>)),
+
+ ok.
+
+bool(X) when is_boolean(X) -> ok;
+bool(_) -> error.
+
+
+is_function_2(Config) when is_list(Config) ->
+ true = is_function(id(fun ?MODULE:all/1), 1),
+ true = is_function(id(fun() -> ok end), 0),
+ false = is_function(id(fun ?MODULE:all/1), 0),
+ false = is_function(id(fun() -> ok end), 1),
+
+ F = fun(_) -> ok end,
+ if
+ is_function(F, 1) -> ok
+ end.
+
+tricky(Config) when is_list(Config) ->
+ ?line not_ok = tricky_1(1, 2),
+ ?line not_ok = tricky_1(1, blurf),
+ ?line not_ok = tricky_1(foo, 2),
+ ?line not_ok = tricky_1(a, b),
+
+ ?line false = rb(100000, [1], 42),
+ ?line true = rb(100000, [], 42),
+ ?line true = rb(555, [a,b,c], 19),
+ ok.
+
+tricky_1(X, Y) when abs((X == 1) or (Y == 2)) -> ok;
+tricky_1(_, _) -> not_ok.
+
+%% From dets_v9:read_buckets/11, simplified.
+
+rb(Size, ToRead, SoFar) when SoFar + Size < 81920; ToRead == [] -> true;
+rb(_, _, _) -> false.
+
+
+-define(T(Op,A,B),
+ ok = if A Op B -> ok; true -> error end,
+ ok = if not (A Op B) -> error; true -> ok end,
+ (fun(X, Y, True, False) ->
+ ok = if X Op Y -> ok; true -> error end,
+ ok = if False; X Op Y; False -> ok; true -> error end,
+ ok = if X Op Y, True -> ok; true -> error end,
+ ok = if not (X Op Y) -> error; true -> ok end,
+ ok = if False; not (X Op Y); False -> error; true -> ok end
+ end)(id(A), id(B), id(true), id(false))).
+
+-define(F(Op,A,B),
+ ok = if A Op B -> error; true -> ok end,
+ ok = if not (A Op B) -> ok; true -> error end,
+ (fun(X, Y, True, False) ->
+ ok = if X Op Y -> error; true -> ok end,
+ ok = if False; X Op Y; False -> error; true -> ok end,
+ ok = if not (X Op Y); False -> ok; true -> error end,
+ ok = if not (X Op Y), True -> ok; true -> error end
+ end)(id(A), id(B), id(true), id(false))).
+
+
+rel_ops(Config) when is_list(Config) ->
+ ?line ?T(=/=, 1, 1.0),
+ ?line ?F(=/=, 2, 2),
+ ?line ?F(=/=, {a}, {a}),
+
+ ?line ?F(/=, a, a),
+ ?line ?F(/=, 0, 0.0),
+ ?line ?T(/=, 0, 1),
+ ?line ?F(/=, {a}, {a}),
+
+ ?line ?T(==, 1, 1.0),
+ ?line ?F(==, a, {}),
+
+ ?line ?F(=:=, 1, 1.0),
+ ?line ?T(=:=, 42.0, 42.0),
+
+ ?line ?F(>, a, b),
+ ?line ?T(>, 42, 1.0),
+ ?line ?F(>, 42, 42.0),
+
+ ?line ?T(<, a, b),
+ ?line ?F(<, 42, 1.0),
+ ?line ?F(<, 42, 42.0),
+
+ ?line ?T(=<, 1.5, 5),
+ ?line ?F(=<, -9, -100.344),
+ ?line ?T(=<, 42, 42.0),
+
+ ?line ?T(>=, 42, 42.0),
+ ?line ?F(>=, a, b),
+ ?line ?T(>=, 1.0, 0),
+
+ ok.
+
+-undef(TestOp).
+
+basic_andalso_orelse(Config) when is_list(Config) ->
+ ?line T = id({type,integers,23,42}),
+ ?line 65 = if
+ ((element(1, T) =:= type) andalso (size(T) =:= 4) andalso
+ element(2, T) == integers) ->
+ element(3, T) + element(4, T);
+ true -> error
+ end,
+ ?line 65 = case [] of
+ [] when ((element(1, T) =:= type) andalso (size(T) =:= 4) andalso
+ element(2, T) == integers) ->
+ element(3, T) + element(4, T)
+ end,
+
+ ?line 42 = basic_rt({type,integers,40,2}),
+ ?line 5.0 = basic_rt({vector,{3.0,4.0}}),
+ ?line 20 = basic_rt(['+',3,7]),
+ ?line {'Set',a,b} = basic_rt({{'Set',a,b},{'Set',a,b}}),
+ ?line 12 = basic_rt({klurf,4}),
+
+ ?line error = basic_rt({type,integers,40,2,3}),
+ ?line error = basic_rt({kalle,integers,40,2}),
+ ?line error = basic_rt({kalle,integers,40,2}),
+ ?line error = basic_rt({1,2}),
+ ?line error = basic_rt([]),
+
+ RelProdBody =
+ fun(R1, R2) ->
+ if
+ (erlang:size(R1) =:= 3) andalso (erlang:element(1,R1) =:= 'Set'),
+ (erlang:size(R2) =:= 3) andalso (erlang:element(1,R2) =:= 'Set') ->
+ ok
+ end
+ end,
+
+ ?line ok = RelProdBody({'Set',a,b}, {'Set',a,b}),
+ ok.
+
+basic_rt(T) when is_tuple(T) andalso size(T) =:= 4 andalso element(1, T) =:= type andalso
+ element(2, T) == integers ->
+ element(3, T) + element(4, T);
+basic_rt(T) when is_tuple(T) andalso size(T) =:= 2 andalso element(1, T) =:= vector ->
+ {X,Y} = element(2, T),
+ if
+ is_float(X), is_float(Y) ->
+ math:sqrt(X*X+Y*Y)
+ end;
+basic_rt(['+',A,B]) ->
+ 2*id(A+B);
+basic_rt({R1,R2}) when erlang:size(R1) =:= 3 andalso erlang:element(1,R1) =:= 'Set',
+ erlang:size(R2) =:= 3 andalso erlang:element(1,R2) =:= 'Set' ->
+ R1 = id(R1),
+ R2 = id(R2),
+ R1;
+basic_rt(T) when is_tuple(T) andalso size(T) =:= 2 andalso element(1, T) =:= klurf ->
+ 3*id(element(2, T));
+basic_rt(_) ->
+ error.
+
+traverse_dcd(Config) when is_list(Config) ->
+ L0 = [{log_header,dcd_log,"1.0",a,b,c},{log_header,dcd_log,"2.0",a,b,c},
+ {log_header,dcd_log,"0.0",a,b,c},blurf],
+ {cont,[{log_header,dcd_log,"0.0",a,b,c},blurf],log,funny} =
+ traverse_dcd({cont,L0}, log, funny),
+ L1 = [{log_header,dcd_log,"1.0"}],
+ {cont,L1,log,funny} = traverse_dcd({cont,L1}, log, funny),
+ L2 = [{a,tuple}],
+ {cont,L2,log,funny} = traverse_dcd({cont,L2}, log, funny),
+ ok.
+
+%% The function starts out with 3 arguments in {x,0}, {x,1}, {x,2}.
+%% The outer match of a two tuple will places the first element in {x,3} and
+%% second in {x,4}. The guard for the first clause must make ensure that all of those
+%% registers are restored befor entering the second clause.
+%%
+%% (From mnesia_checkpoint.erl, modified.)
+
+traverse_dcd({Cont,[LogH|Rest]},Log,Fun)
+ when is_tuple(LogH) andalso size(LogH) =:= 6 andalso element(1, LogH) =:= log_header
+andalso erlang:element(2,LogH) == dcd_log,
+is_tuple(LogH) andalso size(LogH) =:= 6 andalso element(1, LogH) =:= log_header
+andalso erlang:element(3,LogH) >= "1.0" ->
+ traverse_dcd({Cont,Rest},Log,Fun);
+traverse_dcd({Cont,Recs},Log,Fun) ->
+ {Cont,Recs,Log,Fun}.
+
+
+check_qlc_hrl(Config) when is_list(Config) ->
+ St = {r1,false,dum},
+ ?line foo = cqlc(qlc, q, [{lc,1,2,3}], St),
+ ?line foo = cqlc(qlc, q, [{lc,1,2,3},b], St),
+ ?line St = cqlc(qlc, q, [], St),
+ ?line St = cqlc(qlc, blurf, [{lc,1,2,3},b], St),
+ ?line St = cqlc(q, q, [{lc,1,2,3},b], St),
+ ?line St = cqlc(qlc, q, [{lc,1,2,3},b,c], St),
+ ?line St = cqlc(qlc, q, [a,b], St),
+ ?line {r1,true,kalle} = cqlc(qlc, q, [{lc,1,2,3},b], {r1,true,kalle}),
+ ok.
+
+%% From erl_lint.erl; original name was check_qlc_hrl/4.
+cqlc(M, F, As, St) ->
+ Arity = length(As),
+ case As of
+ [{lc,_L,_E,_Qs}|_] when M =:= qlc, F =:= q,
+ Arity < 3,
+ not (((element(1, St) =:= r1) orelse fail) and (size(St) =:= 3) and element(2, St)) ->
+ foo;
+ _ ->
+ St
+ end.
+
+
+
+%% Call this function to turn off constant propagation.
+id(I) -> I.
+
+check(F, Result) ->
+ case F() of
+ Result -> ok;
+ Other ->
+ io:format("Expected: ~p\n", [Result]),
+ io:format(" Got: ~p\n", [Other]),
+ test_server:fail()
+ end.
diff --git a/lib/debugger/test/int_SUITE.erl b/lib/debugger/test/int_SUITE.erl
new file mode 100644
index 0000000000..0326325888
--- /dev/null
+++ b/lib/debugger/test/int_SUITE.erl
@@ -0,0 +1,277 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-module(int_SUITE).
+-include("test_server.hrl").
+
+%% Test server specific exports
+-export([all/1]).
+-export([init_per_testcase/2, end_per_testcase/2]).
+
+%% Test cases
+-export([interpret/1, guards/1, list_suite/1, interpretable/1]).
+-export([append/1, append_1/1, append_2/1, member/1, reverse/1]).
+
+%% Default timetrap timeout (set in init_per_testcase)
+-define(default_timeout, ?t:minutes(1)).
+
+init_per_testcase(interpretable, Config) ->
+ ?line Dog=test_server:timetrap(?default_timeout),
+ [{watchdog, Dog}|Config];
+init_per_testcase(_Case, Config) ->
+
+ %% Interpret some existing and non-existing modules
+ ?line DataDir = ?config(data_dir, Config),
+ ?line {module, lists1} = int:i(filename:join([DataDir,lists1])),
+ ?line {module, guards} = int:i(filename:join([DataDir,guards])),
+
+ ?line Dog=test_server:timetrap(?default_timeout),
+ [{watchdog, Dog}|Config].
+
+end_per_testcase(interpretable, Config) ->
+ ?line Dog=?config(watchdog, Config),
+ ?line test_server:timetrap_cancel(Dog),
+ ok;
+end_per_testcase(_Case, Config) ->
+
+ %% Quit interpreting
+ ?line ok = int:n(lists1),
+ ?line ok = int:n(guards),
+
+ ?line Dog=?config(watchdog, Config),
+ ?line test_server:timetrap_cancel(Dog),
+ ?line ok.
+
+all(suite)->
+ [interpret, guards, list_suite, interpretable].
+
+interpret(suite) ->
+ [];
+interpret(doc) ->
+ ["Interpreting modules"];
+interpret(Config) when is_list(Config) ->
+ ?line int:n(int:interpreted()),
+
+ %% Interpret some existing and non-existing modules
+ ?line DataDir = ?config(data_dir, Config),
+ ?line {module, lists1} = int:i(filename:join([DataDir,lists1])),
+ ?line {module, ordsets1} = int:i(filename:join([DataDir,ordsets1])),
+ ?line error = int:i(non_existent_module),
+
+ %% Check that the interpreter has the right view.
+ ?line ExpectedResult = lists:sort([lists1, ordsets1]),
+ ?line Result = int:interpreted(),
+ ?line ExpectedResult = lists:sort(Result),
+
+ %% Uniterpret the modules.
+ ?line ok = int:n(non_existent_module),
+ ?line ok = int:n(lists1),
+ ?line [ordsets1] = int:interpreted(),
+ ?line ok = int:n("ordsets1"),
+ ?line [] = int:interpreted(),
+
+ ok.
+
+guards(suite) ->
+ [];
+guards(doc) ->
+ "Evaluate guards.";
+guards(Config) when is_list(Config) ->
+ ok = guards:guards().
+
+
+list_suite(suite) ->
+ [append, reverse, member].
+
+append(doc) ->
+ ["Tests lists1:append/1 & lists1:append/2"];
+append(suite) ->
+ [append_1, append_2].
+
+append_1(suite) ->
+ [];
+append_1(doc) ->
+ [];
+append_1(Config) when is_list(Config) ->
+ ?line test_server:format("In append_1~n"),
+ ?line test_server:format("code:which(lists1)=~p~n",
+ [code:which(lists1)]),
+ ?line test_server:format("lists1:append([a],[b])=~p~n",
+ [spawn_eval(lists1,append,[[a],[b]])]),
+
+ ?line "abcdef"=spawn_eval(lists1,append,[["abc","def"]]),
+ ?line [hej, du,[glade, [bagare]]]=
+ spawn_eval(lists1,append,[[[hej], [du], [[glade, [bagare]]]]]),
+ ?line [10, [elem]]=spawn_eval(lists1,append,[[[10], [[elem]]]]),
+ ok.
+
+append_2(suite) ->
+ [];
+append_2(doc) ->
+ [];
+append_2(Config) when is_list(Config) ->
+ ?line test_server:format("In append_2~n"),
+ ?line test_server:format("code:which(lists1)=~p~n",
+ [code:which(lists1)]),
+
+ ?line "abcdef"=spawn_eval(lists1,append,["abc", "def"]),
+ ?line [hej, du]=spawn_eval(lists1,append,[[hej], [du]]),
+ ?line [10, [elem]]=spawn_eval(lists1,append,[[10], [[elem]]]),
+ ok.
+
+reverse(suite) ->
+ [];
+reverse(doc) ->
+ [];
+reverse(Config) when is_list(Config) ->
+ ?line ok=reverse_test(0),
+ ?line ok=reverse_test(1),
+ ?line ok=reverse_test(2),
+ ?line ok=reverse_test(537),
+ ok.
+
+reverse_test(0) ->
+ case spawn_eval(lists1,reverse,[[]]) of
+ [] ->
+ ok;
+ _Other ->
+ error
+ end;
+reverse_test(Num) ->
+ List=spawn_eval(lists1,reverse,
+ [['The Element'|lists1:duplicate(Num, 'Ele')]]),
+ case spawn_eval(lists1,reverse,[List]) of
+ ['The Element'|_Rest] ->
+ ok;
+ _Other ->
+ error
+ end.
+
+member(suite) ->
+ [];
+member(doc) ->
+ ["Tests the lists1:member() implementation. The function "
+ "is `non-blocking', and only processes 2000 elements "
+ "at a time.",
+ "This test case depends on lists1:reverse() to work, "
+ "wich is tested in a separate test case."];
+member(Config) when list(Config) ->
+ ?line ok=member_test(0),
+ ?line ok=member_test(1),
+ ?line ok=member_test(100),
+ ?line ok=member_test(537),
+ ok.
+
+member_test(0) ->
+ case spawn_eval(lists1,member,['The Element', []]) of
+ false ->
+ ok;
+ true ->
+ {error, 'Found (!?)'}
+ end;
+member_test(Num) ->
+ List=spawn_eval(lists1,reverse,
+ [['The Element'|spawn_eval(lists1,duplicate,
+ [Num, 'Elem'])]]),
+ case spawn_eval(lists1,member,['The Element', List]) of
+ true ->
+ ok;
+ false ->
+ {error, not_found}
+ end.
+
+spawn_eval(M,F,A) ->
+ Self = self(),
+ spawn(fun() -> evaluator(Self, M,F,A) end),
+ receive
+ Result ->
+ Result
+ end.
+
+evaluator(Pid, M,F,A) ->
+ Pid ! (catch apply(M,F,A)).
+
+interpretable(suite) ->
+ [];
+interpretable(doc) ->
+ ["Test int:interpretable/1"];
+interpretable(Config) when is_list(Config) ->
+
+ %% First make sure that 'lists1' is not loaded
+ case code:is_loaded(lists1) of
+ {file, _Loaded} ->
+ ?line code:purge(lists1),
+ ?line code:delete(lists1),
+ ?line code:purge(lists1);
+ false -> ignore
+ end,
+
+ %% true
+ ?line DataDir = filename:dirname(?config(data_dir, Config)),
+ ?line true = code:add_patha(DataDir),
+ ?line true = int:interpretable(lists1),
+ ?line true = int:interpretable(filename:join([DataDir,lists1])),
+ ?line true = code:del_path(DataDir),
+
+ %% {error, no_src}
+ ?line PrivDir = filename:join(?config(priv_dir, Config), ""),
+ ?line {ok, _} = file:copy(filename:join([DataDir,"lists1.beam"]),
+ filename:join([PrivDir,"lists1.beam"])),
+ ?line true = code:add_patha(PrivDir),
+
+ ?line {error, no_src} = int:interpretable(lists1),
+ ?line ok = file:delete(filename:join([PrivDir,"lists1.beam"])),
+
+ %% {error, no_beam}
+ Src = filename:join([PrivDir,"lists1.erl"]),
+ ?line {ok, _} = file:copy(filename:join([DataDir,"lists1.erl"]),
+ Src),
+ ?line {error, no_beam} = int:interpretable(Src),
+
+ %% {error, no_debug_info}
+ ?line {ok, _} = compile:file(Src, [{outdir,PrivDir}]),
+ ?line {error, no_debug_info} = int:interpretable(Src),
+ ?line {error, no_debug_info} = int:interpretable(lists1),
+ ?line ok = file:delete(Src),
+ ?line true = code:del_path(PrivDir),
+
+ %% {error, badarg}
+ ?line {error, badarg} = int:interpretable(pride),
+ ?line {error, badarg} = int:interpretable("prejudice.erl"),
+
+ %% {error, {app,App}}
+ ?line {error, {app,_}} = int:interpretable(file),
+ ?line {error, {app,_}} = int:interpretable(lists),
+ ?line {error, {app,_}} = int:interpretable(gs),
+ ?line case int:interpretable(dbg_ieval) of
+ {error, {app,_}} ->
+ ok;
+ {error, badarg} ->
+ case code:which(dbg_ieval) of
+ cover_compiled ->
+ ok;
+ Other1 ->
+ ?line ?t:fail({unexpected_result, Other1})
+ end;
+ Other2 ->
+ ?line ?t:fail({unexpected_result, Other2})
+ end,
+
+ ok.
diff --git a/lib/debugger/test/int_SUITE_data/Makefile.src b/lib/debugger/test/int_SUITE_data/Makefile.src
new file mode 100644
index 0000000000..95b96b5d00
--- /dev/null
+++ b/lib/debugger/test/int_SUITE_data/Makefile.src
@@ -0,0 +1,39 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2000-2010. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+EFLAGS=+debug_info
+all: guards.@EMULATOR@ lists1.@EMULATOR@ my_lists.@EMULATOR@ \
+ ordsets1.@EMULATOR@ test.@EMULATOR@ test1.@EMULATOR@
+
+guards.@EMULATOR@: guards.erl
+ erlc $(EFLAGS) guards.erl
+
+lists1.@EMULATOR@: lists1.erl
+ erlc $(EFLAGS) lists1.erl
+
+my_lists.@EMULATOR@: my_lists.erl
+ erlc $(EFLAGS) my_lists.erl
+
+ordsets1.@EMULATOR@: ordsets1.erl
+ erlc $(EFLAGS) ordsets1.erl
+
+test.@EMULATOR@: test.erl
+ erlc $(EFLAGS) test.erl
+
+test1.@EMULATOR@: test1.erl
+ erlc $(EFLAGS) test1.erl
diff --git a/lib/debugger/test/int_SUITE_data/guards.erl b/lib/debugger/test/int_SUITE_data/guards.erl
new file mode 100644
index 0000000000..c847bb6a8c
--- /dev/null
+++ b/lib/debugger/test/int_SUITE_data/guards.erl
@@ -0,0 +1,108 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-module(guards).
+
+-export([guards/0]).
+
+guards() ->
+ ok = t(),
+ ok = f(),
+ ok = ct(1),
+ ok = multi(1),
+ ok = multi(2),
+ ok = multi(3).
+
+%% The following tests are always true.
+t() when integer(42) ->
+ ok;
+t() when float(2.0) ->
+ ok;
+t() when number(7) ->
+ ok;
+t() when number(3.14) ->
+ ok;
+t() when atom(error) ->
+ ok;
+t() when list([a]) ->
+ ok;
+t() when tuple({}) ->
+ ok;
+t() when tuple({1, 2}) ->
+ ok.
+
+%% The following tests are always false.
+f() when integer(a) ->
+ ok;
+f() when float(b) ->
+ ok;
+f() when number(c) ->
+ ok;
+f() when atom(42) ->
+ ok;
+f() when list(33) ->
+ ok;
+f() when list({}) ->
+ ok;
+f() when list({1, 2}) ->
+ ok;
+f() when tuple(33) ->
+ ok;
+f() when tuple([a]) ->
+ ok;
+f() when tuple([]) ->
+ ok;
+f() when tuple(35) ->
+ ok;
+f() ->
+ ok.
+
+%% The following tests are always true.
+ct(X) ->
+ case X of
+ Y when integer(42) ->
+ ok;
+ Y when float(2.0) ->
+ ok;
+ Y when number(7) ->
+ ok;
+ Y when number(3.14) ->
+ ok;
+ Y when atom(error) ->
+ ok;
+ Y when list([a]) ->
+ ok;
+ Y when tuple({}) ->
+ ok;
+ Y when tuple({1, 2}) ->
+ ok
+ end.
+
+multi(X) ->
+ case X of
+ Y when float(Y) ; integer(Y) ->
+ ok;
+ Y when Y > 1, Y < 10 ; atom(Y) ->
+ ok;
+ Y when Y == 4, number(Y) ; list(Y) ->
+ pannkaka;
+ Y when Y==3 ; Y==5 ; Y==6 ->
+ ok
+ end.
diff --git a/lib/debugger/test/int_SUITE_data/lists1.erl b/lib/debugger/test/int_SUITE_data/lists1.erl
new file mode 100644
index 0000000000..0214983c11
--- /dev/null
+++ b/lib/debugger/test/int_SUITE_data/lists1.erl
@@ -0,0 +1,469 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Purpose : Basic lists processing functions.
+
+-module(lists1).
+
+
+-export([member/2, append/2, append/1, subtract/2, reverse/1, reverse/2,
+ nth/2, nthtail/2, prefix/2, suffix/2, last/1,
+ seq/2, seq/3, sum/1, duplicate/2, min/1, max/1, sublist/2, sublist/3,
+ delete/2, sort/1, merge/2, concat/1,
+ flatten/1, flatten/2, flat_length/1, flatlength/1,
+ keymember/3, keysearch/3, keydelete/3, keyreplace/4,
+ keysort/2, keymerge/3, keymap/3, keymap/4]).
+
+-export([all/2,any/2,map/2,flatmap/2,foldl/3,foldr/3,filter/2,zf/2,
+ mapfoldl/3,mapfoldr/3,foreach/2,takewhile/2,dropwhile/2,splitwith/2]).
+-export([all/3,any/3,map/3,flatmap/3,foldl/4,foldr/4,filter/3,zf/3,
+ mapfoldl/4,mapfoldr/4,foreach/3]).
+
+%% member(X, L) -> (true | false)
+%% test if X is a member of the list L
+
+member(X, [X|_]) -> true;
+member(X, [_|Y]) ->
+ member(X, Y);
+member(X, []) -> false.
+
+%% append(X, Y) appends lists X and Y
+
+append(L1, L2) -> L1 ++ L2.
+
+%% append(L) appends the list of lists L
+
+append([E]) -> E;
+append([H|T]) -> H ++ append(T);
+append([]) -> [].
+
+%% subtract(List1, List2) subtract elements in List2 form List1.
+
+subtract(L1, L2) -> L1 -- L2.
+
+%% reverse(L) reverse all elements in the list L
+
+reverse(X) -> reverse(X, []).
+
+reverse([H|T], Y) ->
+ reverse(T, [H|Y]);
+reverse([], X) -> X.
+
+%% nth(N, L) returns the N`th element of the list L
+%% nthtail(N, L) returns the N`th tail of the list L
+
+nth(1, [H|T]) -> H;
+nth(N, [_|T]) when N > 1 ->
+ nth(N - 1, T).
+
+nthtail(1, [H|T]) -> T;
+nthtail(N, [H|T]) when N > 1 ->
+ nthtail(N - 1, T);
+nthtail(0, L) when list(L) -> L.
+
+%% prefix(Prefix, List) -> (true | false)
+
+prefix([X|PreTail], [X|Tail]) ->
+ prefix(PreTail, Tail);
+prefix([], List) -> true;
+prefix(_,_) -> false.
+
+
+%% suffix(Suffix, List) -> (true | false)
+
+suffix(Suffix, Suffix) -> true;
+suffix(Suffix, [_|Tail]) ->
+ suffix(Suffix, Tail);
+suffix(Suffix, []) -> false.
+
+%% last(List) returns the last element in a list.
+
+last([E]) -> E;
+last([E|Es]) ->
+ last(Es).
+
+%% seq(Min, Max) -> [Min,Min+1, ..., Max]
+%% seq(Min, Max, Incr) -> [Min,Min+Incr, ..., Max]
+%% returns the sequence Min..Max
+%% Min <= Max and Min and Max must be integers
+
+seq(Min, Max) when integer(Min), integer(Max), Min =< Max ->
+ seq(Min, Max, 1, []).
+
+seq(Min, Max, Incr) ->
+ seq(Min, Min + ((Max-Min) div Incr) * Incr, Incr, []).
+
+seq(Min, Min, I, L) -> [Min|L];
+seq(Min, Max, I, L) -> seq(Min, Max-I, I, [Max|L]).
+
+%% sum(L) suns the sum of the elements in L
+
+sum(L) -> sum(L, 0).
+sum([H|T], Sum) -> sum(T, Sum + H);
+sum([], Sum) -> Sum.
+
+%% duplicate(N, X) -> [X,X,X,.....,X] (N times)
+%% return N copies of X
+
+duplicate(N, X) when integer(N), N >= 0 -> duplicate(N, X, []).
+
+duplicate(0, _, L) -> L;
+duplicate(N, X, L) -> duplicate(N-1, X, [X|L]).
+
+
+%% min(L) -> returns the minimum element of the list L
+
+min([H|T]) -> min(T, H).
+
+min([H|T], Min) when H < Min -> min(T, H);
+min([_|T], Min) -> min(T, Min);
+min([], Min) -> Min.
+
+%% max(L) -> returns the maximum element of the list L
+
+max([H|T]) -> max(T, H).
+
+max([H|T], Max) when H > Max -> max(T, H);
+max([_|T], Max) -> max(T, Max);
+max([], Max) -> Max.
+
+%% sublist(List, Start, Length)
+%% Returns the sub-list starting at Start of length Length.
+
+sublist(List, S, L) when L >= 0 ->
+ sublist(nthtail(S-1, List), L).
+
+sublist([H|T], L) when L > 0 ->
+ [H|sublist(T, L-1)];
+sublist(List, L) -> [].
+
+%% delete(Item, List) -> List'
+%% Delete the first occurance of Item from the list L.
+
+delete(Item, [Item|Rest]) -> Rest;
+delete(Item, [H|Rest]) ->
+ [H|delete(Item, Rest)];
+delete(Item, []) -> [].
+
+%% sort(L) -> sorts the list L
+
+sort([X]) -> [X];
+sort([]) -> [];
+sort(X) -> split_and_sort(X, [], []).
+
+split_and_sort([A,B|T], X, Y) ->
+ split_and_sort(T, [A|X], [B|Y]);
+split_and_sort([H], X, Y) ->
+ split_and_sort([], [H|X], Y);
+split_and_sort([], X, Y) ->
+ merge(sort(X), sort(Y), []).
+
+%% merge(X, Y) -> L
+%% merges two sorted lists X and Y
+
+merge(X, Y) -> merge(X, Y, []).
+
+merge([H1|T1], [H2|T2], L) when H1 < H2 ->
+ merge(T1, [H2|T2], [H1|L]);
+merge(T1, [H2|T2], L) ->
+ merge(T1, T2, [H2|L]);
+merge([H|T], T2, L) ->
+ merge(T, T2, [H|L]);
+merge([], [], L) ->
+ reverse(L).
+
+%% concat(L) concatinate the list representation of the elements
+%% in L - the elements in L can be atoms, integers of strings.
+%% Returns a list of characters.
+
+concat(List) ->
+ flatmap(fun thing_to_list/1, List).
+
+thing_to_list(X) when integer(X) -> integer_to_list(X);
+thing_to_list(X) when float(X) -> float_to_list(X);
+thing_to_list(X) when atom(X) -> atom_to_list(X);
+thing_to_list(X) when list(X) -> X. %Assumed to be a string
+
+%% flatten(List)
+%% flatten(List, Tail)
+%% Flatten a list, adding optional tail.
+
+flatten(List) ->
+ flatten(List, [], []).
+
+flatten(List, Tail) ->
+ flatten(List, [], Tail).
+
+flatten([H|T], Cont, Tail) when list(H) ->
+ flatten(H, [T|Cont], Tail);
+flatten([H|T], Cont, Tail) ->
+ [H|flatten(T, Cont, Tail)];
+flatten([], [H|Cont], Tail) ->
+ flatten(H, Cont, Tail);
+flatten([], [], Tail) ->
+ Tail.
+
+%% flat_length(List) (undocumented can be rmove later)
+%% Calculate the length of a list of lists.
+
+flat_length(List) -> flatlength(List).
+
+%% flatlength(List)
+%% Calculate the length of a list of lists.
+
+flatlength(List) ->
+ flatlength(List, 0).
+
+flatlength([H|T], L) when list(H) ->
+ flatlength(H, flatlength(T, L));
+flatlength([H|T], L) ->
+ flatlength(T, L + 1);
+flatlength([], L) -> L.
+
+%% keymember(Key, Index, [Tuple])
+%% keysearch(Key, Index, [Tuple])
+%% keydelete(Key, Index, [Tuple])
+%% keyreplace(Key, Index, [Tuple], NewTuple)
+%% keysort(Index, [Tuple])
+%% keymerge(Index, [Tuple], [Tuple])
+%% keymap(Function, Index, [Tuple])
+%% keymap(Function, ExtraArgs, Index, [Tuple])
+
+keymember(Key, N, [T|Ts]) when element(N, T) == Key -> true;
+keymember(Key, N, [T|Ts]) ->
+ keymember(Key, N, Ts);
+keymember(Key, N, []) -> false.
+
+keysearch(Key, N, [H|T]) when element(N, H) == Key ->
+ {value, H};
+keysearch(Key, N, [H|T]) ->
+ keysearch(Key, N, T);
+keysearch(Key, N, []) -> false.
+
+keydelete(Key, N, [H|T]) when element(N, H) == Key -> T;
+keydelete(Key, N, [H|T]) ->
+ [H|keydelete(Key, N, T)];
+keydelete(Key, N, []) -> [].
+
+keyreplace(Key, Pos, [Tup|Tail], New) when element(Pos, Tup) == Key ->
+ [New|Tail];
+keyreplace(Key, Pos, [H|T], New) ->
+ [H|keyreplace(Key, Pos, T, New)];
+keyreplace(Key, Pos, [], New) -> [].
+
+keysort(Index, [X]) -> [X];
+keysort(Index, []) -> [];
+keysort(Index, X) -> split_and_keysort(X, [], [], Index).
+
+split_and_keysort([A,B|T], X, Y, Index) ->
+ split_and_keysort(T, [A|X], [B|Y], Index);
+split_and_keysort([H], X, Y, Index) ->
+ split_and_keysort([], [H|X], Y, Index);
+split_and_keysort([], X, Y, Index) ->
+ keymerge(Index, keysort(Index, X), keysort(Index, Y), []).
+
+keymerge(Index, X, Y) -> keymerge(Index, X, Y, []).
+
+keymerge(I, [H1|T1], [H2|T2], L) when element(I, H1) < element(I, H2) ->
+ keymerge(I, T1, [H2|T2], [H1|L]);
+keymerge(Index, T1, [H2|T2], L) ->
+ keymerge(Index,T1, T2, [H2|L]);
+keymerge(Index,[H|T], T2, L) ->
+ keymerge(Index,T, T2, [H|L]);
+keymerge(Index, [], [], L) ->
+ reverse(L).
+
+keymap(Fun, Index, [Tup|Tail]) ->
+ [setelement(Index, Tup, Fun(element(Index, Tup)))|keymap(Fun, Index, Tail)];
+keymap( _, _ , []) -> [].
+
+keymap(Fun, ExtraArgs, Index, [Tup|Tail]) ->
+ [setelement(Index, Tup, apply(Fun, [element(Index, Tup)|ExtraArgs]))|
+ keymap(Fun, ExtraArgs, Index, Tail)];
+keymap( _, _ , _, []) -> [].
+
+%% all(Predicate, List)
+%% any(Predicate, List)
+%% map(Function, List)
+%% flatmap(Function, List)
+%% foldl(Function, First, List)
+%% foldr(Function, Last, List)
+%% filter(Predicate, List)
+%% zf(Function, List)
+%% mapfoldl(Function, First, List)
+%% mapfoldr(Function, Last, List)
+%% foreach(Function, List)
+%% takewhile(Predicate, List)
+%% dropwhile(Predicate, List)
+%% splitwith(Predicate, List)
+%% for list programming. Function here is either a 'fun' or a tuple
+%% {Module,Name} and we use apply/2 to evaluate. The name zf is a joke!
+%%
+%% N.B. Unless where the functions actually needs it only foreach/2/3,
+%% which is meant to be used for its side effects, has a defined order
+%% of evaluation.
+%%
+%% There are also versions with an extra argument, ExtraArgs, which is a
+%% list of extra arguments to each call.
+
+all(Pred, [Hd|Tail]) ->
+ case Pred(Hd) of
+ true -> all(Pred, Tail);
+ false -> false
+ end;
+all(Pred, []) -> true.
+
+any(Pred, [Hd|Tail]) ->
+ case Pred(Hd) of
+ true -> true;
+ false -> any(Pred, Tail)
+ end;
+any(Pred, []) -> false.
+
+map(F, List) -> [ F(E) || E <- List ].
+
+flatmap(F, [Hd|Tail]) ->
+ F(Hd) ++ flatmap(F, Tail);
+flatmap(F, []) -> [].
+
+foldl(F, Accu, [Hd|Tail]) ->
+ foldl(F, F(Hd, Accu), Tail);
+foldl(F, Accu, []) -> Accu.
+
+foldr(F, Accu, [Hd|Tail]) ->
+ F(Hd, foldr(F, Accu, Tail));
+foldr(F, Accu, []) -> Accu.
+
+filter(Pred, List) -> [ E || E <- List, Pred(E) ].
+
+zf(F, [Hd|Tail]) ->
+ case F(Hd) of
+ true ->
+ [Hd|zf(F, Tail)];
+ {true,Val} ->
+ [Val|zf(F, Tail)];
+ false ->
+ zf(F, Tail)
+ end;
+zf(F, []) -> [].
+
+foreach(F, [Hd|Tail]) ->
+ F(Hd),
+ foreach(F, Tail);
+foreach(F, []) -> ok.
+
+mapfoldl(F, Accu0, [Hd|Tail]) ->
+ {R,Accu1} = F(Hd, Accu0),
+ {Rs,Accu2} = mapfoldl(F, Accu1, Tail),
+ {[R|Rs],Accu2};
+mapfoldl(F, Accu, []) -> {[],Accu}.
+
+mapfoldr(F, Accu0, [Hd|Tail]) ->
+ {Rs,Accu1} = mapfoldr(F, Accu0, Tail),
+ {R,Accu2} = F(Hd, Accu1),
+ {[R|Rs],Accu2};
+mapfoldr(F, Accu, []) -> {[],Accu}.
+
+takewhile(Pred, [Hd|Tail]) ->
+ case Pred(Hd) of
+ true -> [Hd|takewhile(Pred, Tail)];
+ false -> []
+ end;
+takewhile(Pred, []) -> [].
+
+dropwhile(Pred, [Hd|Tail]) ->
+ case Pred(Hd) of
+ true -> dropwhile(Pred, Tail);
+ false -> [Hd|Tail]
+ end;
+dropwhile(Pred, []) -> [].
+
+splitwith(Pred, List) -> splitwith(Pred, List, []).
+
+splitwith(Pred, [Hd|Tail], Taken) ->
+ case Pred(Hd) of
+ true -> splitwith(Pred, Tail, [Hd|Taken]);
+ false -> {reverse(Taken), [Hd|Tail]}
+ end;
+splitwith(Pred, [], Taken) -> {reverse(Taken),[]}.
+
+%% Versions of the above functions with extra arguments.
+
+all(Pred, Eas, [Hd|Tail]) ->
+ case apply(Pred, [Hd|Eas]) of
+ true -> all(Pred, Eas, Tail);
+ false -> false
+ end;
+all(Pred, Eas, []) -> true.
+
+any(Pred, Eas, [Hd|Tail]) ->
+ case apply(Pred, [Hd|Eas]) of
+ true -> true;
+ false -> any(Pred, Eas, Tail)
+ end;
+any(Pred, Eas, []) -> false.
+
+map(F, Eas, List) -> [ apply(F, [E|Eas]) || E <- List ].
+
+flatmap(F, Eas, [Hd|Tail]) ->
+ apply(F, [Hd|Eas]) ++ flatmap(F, Eas, Tail);
+flatmap(F, Eas, []) -> [].
+
+foldl(F, Eas, Accu, [Hd|Tail]) ->
+ foldl(F, Eas, apply(F, [Hd,Accu|Eas]), Tail);
+foldl(F, Eas, Accu, []) -> Accu.
+
+foldr(F, Eas, Accu, [Hd|Tail]) ->
+ apply(F, [Hd,foldr(F, Eas, Accu, Tail)|Eas]);
+foldr(F, Eas, Accu, []) ->
+ Accu.
+
+filter(Pred, Eas, List) -> [ E || E <- List, apply(Pred, [E|Eas]) ].
+
+zf(F, Eas, [Hd|Tail]) ->
+ case apply(F, [Hd|Eas]) of
+ true ->
+ [Hd|zf(F, Eas, Tail)];
+ {true,Val} ->
+ [Val|zf(F, Eas, Tail)];
+ false ->
+ zf(F, Eas, Tail)
+ end;
+zf(F, Eas, []) -> [].
+
+foreach(F, Eas, [Hd|Tail]) ->
+ apply(F, [Hd|Eas]),
+ foreach(F, Eas, Tail);
+foreach(F, Eas, []) -> ok.
+
+mapfoldl(F, Eas, Accu0, [Hd|Tail]) ->
+ {R,Accu1} = apply(F, [Hd,Accu0|Eas]),
+ {Rs,Accu2} = mapfoldl(F, Eas, Accu1, Tail),
+ {[R|Rs],Accu2};
+mapfoldl(F, Eas, Accu, []) -> {[],Accu}.
+
+mapfoldr(F, Eas, Accu0, [Hd|Tail]) ->
+ {Rs,Accu1} = mapfoldr(F, Eas, Accu0, Tail),
+ {R,Accu2} = apply(F, [Hd,Accu1|Eas]),
+ {[R|Rs],Accu2};
+mapfoldr(F, Eas, Accu, []) -> {[],Accu}.
+
+%% takewhile/2, dropwhile/2 and splitwith/2 do not have versions with
+%% extra arguments as this going to be discontinued.
diff --git a/lib/debugger/test/int_SUITE_data/my_lists.erl b/lib/debugger/test/int_SUITE_data/my_lists.erl
new file mode 100644
index 0000000000..98eb4396e3
--- /dev/null
+++ b/lib/debugger/test/int_SUITE_data/my_lists.erl
@@ -0,0 +1,5681 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%% A rather large file to test the attach delay.
+%%% Use only the ordinary lists commands.
+
+-module(my_lists).
+
+
+-export([member/2, append/2, append/1, subtract/2, reverse/1, reverse/2,
+ nth/2, nthtail/2, prefix/2, suffix/2, last/1,
+ seq/2, seq/3, sum/1, duplicate/2, min/1, max/1, sublist/2, sublist/3,
+ delete/2, sort/1, merge/2, concat/1,
+ flatten/1, flatten/2, flat_length/1, flatlength/1,
+ keymember/3, keysearch/3, keydelete/3, keyreplace/4,
+ keysort/2, keymerge/3, keymap/3, keymap/4]).
+
+-export([all/2,any/2,map/2,flatmap/2,foldl/3,foldr/3,filter/2,zf/2,
+ mapfoldl/3,mapfoldr/3,foreach/2,takewhile/2,dropwhile/2,splitwith/2]).
+-export([all/3,any/3,map/3,flatmap/3,foldl/4,foldr/4,filter/3,zf/3,
+ mapfoldl/4,mapfoldr/4,foreach/3]).
+
+%% member(X, L) -> (true | false)
+%% test if X is a member of the list L
+
+member(X, [X|_]) -> true;
+member(X, [_|Y]) ->
+ member(X, Y);
+member(X, []) -> false.
+
+%% append(X, Y) appends lists X and Y
+
+append(L1, L2) -> L1 ++ L2.
+
+%% append(L) appends the list of lists L
+
+append([E]) -> E;
+append([H|T]) -> H ++ append(T);
+append([]) -> [].
+
+%% subtract(List1, List2) subtract elements in List2 form List1.
+
+subtract(L1, L2) -> L1 -- L2.
+
+%% reverse(L) reverse all elements in the list L
+
+reverse(X) -> reverse(X, []).
+
+reverse([H|T], Y) ->
+ reverse(T, [H|Y]);
+reverse([], X) -> X.
+
+%% nth(N, L) returns the N`th element of the list L
+%% nthtail(N, L) returns the N`th tail of the list L
+
+nth(1, [H|T]) -> H;
+nth(N, [_|T]) when N > 1 ->
+ nth(N - 1, T).
+
+nthtail(1, [H|T]) -> T;
+nthtail(N, [H|T]) when N > 1 ->
+ nthtail(N - 1, T);
+nthtail(0, L) when list(L) -> L.
+
+%% prefix(Prefix, List) -> (true | false)
+
+prefix([X|PreTail], [X|Tail]) ->
+ prefix(PreTail, Tail);
+prefix([], List) -> true;
+prefix(_,_) -> false.
+
+
+%% suffix(Suffix, List) -> (true | false)
+
+suffix(Suffix, Suffix) -> true;
+suffix(Suffix, [_|Tail]) ->
+ suffix(Suffix, Tail);
+suffix(Suffix, []) -> false.
+
+%% last(List) returns the last element in a list.
+
+last([E]) -> E;
+last([E|Es]) ->
+ last(Es).
+
+%% seq(Min, Max) -> [Min,Min+1, ..., Max]
+%% seq(Min, Max, Incr) -> [Min,Min+Incr, ..., Max]
+%% returns the sequence Min..Max
+%% Min <= Max and Min and Max must be integers
+
+seq(Min, Max) when integer(Min), integer(Max), Min =< Max ->
+ seq(Min, Max, 1, []).
+
+seq(Min, Max, Incr) ->
+ seq(Min, Min + ((Max-Min) div Incr) * Incr, Incr, []).
+
+seq(Min, Min, I, L) -> [Min|L];
+seq(Min, Max, I, L) -> seq(Min, Max-I, I, [Max|L]).
+
+%% sum(L) suns the sum of the elements in L
+
+sum(L) -> sum(L, 0).
+sum([H|T], Sum) -> sum(T, Sum + H);
+sum([], Sum) -> Sum.
+
+%% duplicate(N, X) -> [X,X,X,.....,X] (N times)
+%% return N copies of X
+
+duplicate(N, X) when integer(N), N >= 0 -> duplicate(N, X, []).
+
+duplicate(0, _, L) -> L;
+duplicate(N, X, L) -> duplicate(N-1, X, [X|L]).
+
+
+%% min(L) -> returns the minimum element of the list L
+
+min([H|T]) -> min(T, H).
+
+min([H|T], Min) when H < Min -> min(T, H);
+min([_|T], Min) -> min(T, Min);
+min([], Min) -> Min.
+
+%% max(L) -> returns the maximum element of the list L
+
+max([H|T]) -> max(T, H).
+
+max([H|T], Max) when H > Max -> max(T, H);
+max([_|T], Max) -> max(T, Max);
+max([], Max) -> Max.
+
+%% sublist(List, Start, Length)
+%% Returns the sub-list starting at Start of length Length.
+
+sublist(List, S, L) when L >= 0 ->
+ sublist(nthtail(S-1, List), L).
+
+sublist([H|T], L) when L > 0 ->
+ [H|sublist(T, L-1)];
+sublist(List, L) -> [].
+
+%% delete(Item, List) -> List'
+%% Delete the first occurance of Item from the list L.
+
+delete(Item, [Item|Rest]) -> Rest;
+delete(Item, [H|Rest]) ->
+ [H|delete(Item, Rest)];
+delete(Item, []) -> [].
+
+%% sort(L) -> sorts the list L
+
+sort([X]) -> [X];
+sort([]) -> [];
+sort(X) -> split_and_sort(X, [], []).
+
+split_and_sort([A,B|T], X, Y) ->
+ split_and_sort(T, [A|X], [B|Y]);
+split_and_sort([H], X, Y) ->
+ split_and_sort([], [H|X], Y);
+split_and_sort([], X, Y) ->
+ merge(sort(X), sort(Y), []).
+
+%% merge(X, Y) -> L
+%% merges two sorted lists X and Y
+
+merge(X, Y) -> merge(X, Y, []).
+
+merge([H1|T1], [H2|T2], L) when H1 < H2 ->
+ merge(T1, [H2|T2], [H1|L]);
+merge(T1, [H2|T2], L) ->
+ merge(T1, T2, [H2|L]);
+merge([H|T], T2, L) ->
+ merge(T, T2, [H|L]);
+merge([], [], L) ->
+ reverse(L).
+
+%% concat(L) concatinate the list representation of the elements
+%% in L - the elements in L can be atoms, integers of strings.
+%% Returns a list of characters.
+
+concat(List) ->
+ flatmap(fun thing_to_list/1, List).
+
+thing_to_list(X) when integer(X) -> integer_to_list(X);
+thing_to_list(X) when float(X) -> float_to_list(X);
+thing_to_list(X) when atom(X) -> atom_to_list(X);
+thing_to_list(X) when list(X) -> X. %Assumed to be a string
+
+%% flatten(List)
+%% flatten(List, Tail)
+%% Flatten a list, adding optional tail.
+
+flatten(List) ->
+ flatten(List, [], []).
+
+flatten(List, Tail) ->
+ flatten(List, [], Tail).
+
+flatten([H|T], Cont, Tail) when list(H) ->
+ flatten(H, [T|Cont], Tail);
+flatten([H|T], Cont, Tail) ->
+ [H|flatten(T, Cont, Tail)];
+flatten([], [H|Cont], Tail) ->
+ flatten(H, Cont, Tail);
+flatten([], [], Tail) ->
+ Tail.
+
+%% flat_length(List) (undocumented can be rmove later)
+%% Calculate the length of a list of lists.
+
+flat_length(List) -> flatlength(List).
+
+%% flatlength(List)
+%% Calculate the length of a list of lists.
+
+flatlength(List) ->
+ flatlength(List, 0).
+
+flatlength([H|T], L) when list(H) ->
+ flatlength(H, flatlength(T, L));
+flatlength([H|T], L) ->
+ flatlength(T, L + 1);
+flatlength([], L) -> L.
+
+%% keymember(Key, Index, [Tuple])
+%% keysearch(Key, Index, [Tuple])
+%% keydelete(Key, Index, [Tuple])
+%% keyreplace(Key, Index, [Tuple], NewTuple)
+%% keysort(Index, [Tuple])
+%% keymerge(Index, [Tuple], [Tuple])
+%% keymap(Function, Index, [Tuple])
+%% keymap(Function, ExtraArgs, Index, [Tuple])
+
+keymember(Key, N, [T|Ts]) when element(N, T) == Key -> true;
+keymember(Key, N, [T|Ts]) ->
+ keymember(Key, N, Ts);
+keymember(Key, N, []) -> false.
+
+keysearch(Key, N, [H|T]) when element(N, H) == Key ->
+ {value, H};
+keysearch(Key, N, [H|T]) ->
+ keysearch(Key, N, T);
+keysearch(Key, N, []) -> false.
+
+keydelete(Key, N, [H|T]) when element(N, H) == Key -> T;
+keydelete(Key, N, [H|T]) ->
+ [H|keydelete(Key, N, T)];
+keydelete(Key, N, []) -> [].
+
+keyreplace(Key, Pos, [Tup|Tail], New) when element(Pos, Tup) == Key ->
+ [New|Tail];
+keyreplace(Key, Pos, [H|T], New) ->
+ [H|keyreplace(Key, Pos, T, New)];
+keyreplace(Key, Pos, [], New) -> [].
+
+keysort(Index, [X]) -> [X];
+keysort(Index, []) -> [];
+keysort(Index, X) -> split_and_keysort(X, [], [], Index).
+
+split_and_keysort([A,B|T], X, Y, Index) ->
+ split_and_keysort(T, [A|X], [B|Y], Index);
+split_and_keysort([H], X, Y, Index) ->
+ split_and_keysort([], [H|X], Y, Index);
+split_and_keysort([], X, Y, Index) ->
+ keymerge(Index, keysort(Index, X), keysort(Index, Y), []).
+
+keymerge(Index, X, Y) -> keymerge(Index, X, Y, []).
+
+keymerge(I, [H1|T1], [H2|T2], L) when element(I, H1) < element(I, H2) ->
+ keymerge(I, T1, [H2|T2], [H1|L]);
+keymerge(Index, T1, [H2|T2], L) ->
+ keymerge(Index,T1, T2, [H2|L]);
+keymerge(Index,[H|T], T2, L) ->
+ keymerge(Index,T, T2, [H|L]);
+keymerge(Index, [], [], L) ->
+ reverse(L).
+
+keymap(Fun, Index, [Tup|Tail]) ->
+ [setelement(Index, Tup, Fun(element(Index, Tup)))|keymap(Fun, Index, Tail)];
+keymap( _, _ , []) -> [].
+
+keymap(Fun, ExtraArgs, Index, [Tup|Tail]) ->
+ [setelement(Index, Tup, apply(Fun, [element(Index, Tup)|ExtraArgs]))|
+ keymap(Fun, ExtraArgs, Index, Tail)];
+keymap( _, _ , _, []) -> [].
+
+%% all(Predicate, List)
+%% any(Predicate, List)
+%% map(Function, List)
+%% flatmap(Function, List)
+%% foldl(Function, First, List)
+%% foldr(Function, Last, List)
+%% filter(Predicate, List)
+%% zf(Function, List)
+%% mapfoldl(Function, First, List)
+%% mapfoldr(Function, Last, List)
+%% foreach(Function, List)
+%% takewhile(Predicate, List)
+%% dropwhile(Predicate, List)
+%% splitwith(Predicate, List)
+%% for list programming. Function here is either a 'fun' or a tuple
+%% {Module,Name} and we use apply/2 to evaluate. The name zf is a joke!
+%%
+%% N.B. Unless where the functions actually needs it only foreach/2/3,
+%% which is meant to be used for its side effects, has a defined order
+%% of evaluation.
+%%
+%% There are also versions with an extra argument, ExtraArgs, which is a
+%% list of extra arguments to each call.
+
+all(Pred, [Hd|Tail]) ->
+ case Pred(Hd) of
+ true -> all(Pred, Tail);
+ false -> false
+ end;
+all(Pred, []) -> true.
+
+any(Pred, [Hd|Tail]) ->
+ case Pred(Hd) of
+ true -> true;
+ false -> any(Pred, Tail)
+ end;
+any(Pred, []) -> false.
+
+map(F, List) -> [ F(E) || E <- List ].
+
+flatmap(F, [Hd|Tail]) ->
+ F(Hd) ++ flatmap(F, Tail);
+flatmap(F, []) -> [].
+
+foldl(F, Accu, [Hd|Tail]) ->
+ foldl(F, F(Hd, Accu), Tail);
+foldl(F, Accu, []) -> Accu.
+
+foldr(F, Accu, [Hd|Tail]) ->
+ F(Hd, foldr(F, Accu, Tail));
+foldr(F, Accu, []) -> Accu.
+
+filter(Pred, List) -> [ E || E <- List, Pred(E) ].
+
+zf(F, [Hd|Tail]) ->
+ case F(Hd) of
+ true ->
+ [Hd|zf(F, Tail)];
+ {true,Val} ->
+ [Val|zf(F, Tail)];
+ false ->
+ zf(F, Tail)
+ end;
+zf(F, []) -> [].
+
+foreach(F, [Hd|Tail]) ->
+ F(Hd),
+ foreach(F, Tail);
+foreach(F, []) -> ok.
+
+mapfoldl(F, Accu0, [Hd|Tail]) ->
+ {R,Accu1} = F(Hd, Accu0),
+ {Rs,Accu2} = mapfoldl(F, Accu1, Tail),
+ {[R|Rs],Accu2};
+mapfoldl(F, Accu, []) -> {[],Accu}.
+
+mapfoldr(F, Accu0, [Hd|Tail]) ->
+ {Rs,Accu1} = mapfoldr(F, Accu0, Tail),
+ {R,Accu2} = F(Hd, Accu1),
+ {[R|Rs],Accu2};
+mapfoldr(F, Accu, []) -> {[],Accu}.
+
+takewhile(Pred, [Hd|Tail]) ->
+ case Pred(Hd) of
+ true -> [Hd|takewhile(Pred, Tail)];
+ false -> []
+ end;
+takewhile(Pred, []) -> [].
+
+dropwhile(Pred, [Hd|Tail]) ->
+ case Pred(Hd) of
+ true -> dropwhile(Pred, Tail);
+ false -> [Hd|Tail]
+ end;
+dropwhile(Pred, []) -> [].
+
+splitwith(Pred, List) -> splitwith(Pred, List, []).
+
+splitwith(Pred, [Hd|Tail], Taken) ->
+ case Pred(Hd) of
+ true -> splitwith(Pred, Tail, [Hd|Taken]);
+ false -> {reverse(Taken), [Hd|Tail]}
+ end;
+splitwith(Pred, [], Taken) -> {reverse(Taken),[]}.
+
+%% Versions of the above functions with extra arguments.
+
+all(Pred, Eas, [Hd|Tail]) ->
+ case apply(Pred, [Hd|Eas]) of
+ true -> all(Pred, Eas, Tail);
+ false -> false
+ end;
+all(Pred, Eas, []) -> true.
+
+any(Pred, Eas, [Hd|Tail]) ->
+ case apply(Pred, [Hd|Eas]) of
+ true -> true;
+ false -> any(Pred, Eas, Tail)
+ end;
+any(Pred, Eas, []) -> false.
+
+map(F, Eas, List) -> [ apply(F, [E|Eas]) || E <- List ].
+
+flatmap(F, Eas, [Hd|Tail]) ->
+ apply(F, [Hd|Eas]) ++ flatmap(F, Eas, Tail);
+flatmap(F, Eas, []) -> [].
+
+foldl(F, Eas, Accu, [Hd|Tail]) ->
+ foldl(F, Eas, apply(F, [Hd,Accu|Eas]), Tail);
+foldl(F, Eas, Accu, []) -> Accu.
+
+foldr(F, Eas, Accu, [Hd|Tail]) ->
+ apply(F, [Hd,foldr(F, Eas, Accu, Tail)|Eas]);
+foldr(F, Eas, Accu, []) ->
+ Accu.
+
+filter(Pred, Eas, List) -> [ E || E <- List, apply(Pred, [E|Eas]) ].
+
+zf(F, Eas, [Hd|Tail]) ->
+ case apply(F, [Hd|Eas]) of
+ true ->
+ [Hd|zf(F, Eas, Tail)];
+ {true,Val} ->
+ [Val|zf(F, Eas, Tail)];
+ false ->
+ zf(F, Eas, Tail)
+ end;
+zf(F, Eas, []) -> [].
+
+foreach(F, Eas, [Hd|Tail]) ->
+ apply(F, [Hd|Eas]),
+ foreach(F, Eas, Tail);
+foreach(F, Eas, []) -> ok.
+
+mapfoldl(F, Eas, Accu0, [Hd|Tail]) ->
+ {R,Accu1} = apply(F, [Hd,Accu0|Eas]),
+ {Rs,Accu2} = mapfoldl(F, Eas, Accu1, Tail),
+ {[R|Rs],Accu2};
+mapfoldl(F, Eas, Accu, []) -> {[],Accu}.
+
+mapfoldr(F, Eas, Accu0, [Hd|Tail]) ->
+ {Rs,Accu1} = mapfoldr(F, Eas, Accu0, Tail),
+ {R,Accu2} = apply(F, [Hd,Accu1|Eas]),
+ {[R|Rs],Accu2};
+mapfoldr(F, Eas, Accu, []) -> {[],Accu}.
+
+%% takewhile/2, dropwhile/2 and splitwith/2 do not have versions with
+%% extra arguments as this going to be discontinued.
+
+
+
+
+
+%%% +++++++++++++++++++++++++++++++++++++++
+%%%
+%%% Same as above but with "_1" added to the function names
+%%%
+
+
+%% member_1(X, L) -> (true | false)
+%% test if X is a member of the list L
+
+%member_1(X, [X|_]) -> true;
+%member_1(X, [_|Y]) ->
+% member_1(X, Y);
+%member_1(X, []) -> false.
+
+member_1(X, L) when list(L) ->
+ case erlang:member_1(X, L) of
+ L1 when list(L1) ->
+ receive after 1 -> ok end,
+ member_1(X, L1);
+ Boolean ->
+ Boolean
+ end.
+
+%% append_1(X, Y) appends lists X and Y
+
+append_1(L1, L2) -> L1 ++ L2.
+
+%% append_1(L) appends the list of lists L
+
+append_1([E]) -> E;
+append_1([H|T]) -> H ++ append_1(T);
+append_1([]) -> [].
+
+%% subtract_1(List1, List2) subtract elements in List2 form List1.
+
+subtract_1(L1, L2) -> L1 -- L2.
+
+%% reverse_1(L) reverse all elements in the list L
+
+reverse_1(X) -> reverse_1(X, []).
+
+%reverse_1([H|T], Y) ->
+% reverse_1(T, [H|Y]);
+%reverse_1([], X) -> X.
+
+reverse_1(List0, Result0) when list(List0) ->
+ case erlang:reverse_1(List0, Result0) of
+ {List, Result} ->
+ receive after 1 -> ok end,
+ reverse_1(List, Result);
+ Result ->
+ Result
+ end.
+
+
+%% nth_1(N, L) returns the N`th element of the list L
+%% nthtail_1(N, L) returns the N`th tail of the list L
+
+nth_1(1, [H|T]) -> H;
+nth_1(N, [_|T]) when N > 1 ->
+ nth_1(N - 1, T).
+
+nthtail_1(1, [H|T]) -> T;
+nthtail_1(N, [H|T]) when N > 1 ->
+ nthtail_1(N - 1, T);
+nthtail_1(0, L) when list(L) -> L.
+
+%% prefix_1(Prefix, List) -> (true | false)
+
+prefix_1([X|PreTail], [X|Tail]) ->
+ prefix_1(PreTail, Tail);
+prefix_1([], List) -> true;
+prefix_1(_,_) -> false.
+
+
+%% suffix_1(Suffix, List) -> (true | false)
+
+suffix_1(Suffix, Suffix) -> true;
+suffix_1(Suffix, [_|Tail]) ->
+ suffix_1(Suffix, Tail);
+suffix_1(Suffix, []) -> false.
+
+%% last(List) returns the last element in a list.
+
+last_1([E]) -> E;
+last_1([E|Es]) ->
+ last_1(Es).
+
+%% seq(Min, Max) -> [Min,Min+1, ..., Max]
+%% seq(Min, Max, Incr) -> [Min,Min+Incr, ..., Max]
+%% returns the sequence Min..Max
+%% Min <= Max and Min and Max must be integers
+
+seq_1(Min, Max) when integer(Min), integer(Max), Min =< Max ->
+ seq_1(Min, Max, 1, []).
+
+seq_1(Min, Max, Incr) ->
+ seq_1(Min, Min + ((Max-Min) div Incr) * Incr, Incr, []).
+
+seq_1(Min, Min, I, L) -> [Min|L];
+seq_1(Min, Max, I, L) -> seq_1(Min, Max-I, I, [Max|L]).
+
+%% sum(L) suns the sum of the elements in L
+
+sum_1(L) -> sum_1(L, 0).
+sum_1([H|T], Sum) -> sum_1(T, Sum + H);
+sum_1([], Sum) -> Sum.
+
+%% duplicate(N, X) -> [X,X,X,.....,X] (N times)
+%% return N copies of X
+
+duplicate_1(N, X) when integer(N), N >= 0 -> duplicate_1(N, X, []).
+
+duplicate_1(0, _, L) -> L;
+duplicate_1(N, X, L) -> duplicate_1(N-1, X, [X|L]).
+
+
+%% min(L) -> returns the minimum element of the list L
+
+min_1([H|T]) -> min_1(T, H).
+
+min_1([H|T], Min) when H < Min -> min_1(T, H);
+min_1([_|T], Min) -> min_1(T, Min);
+min_1([], Min) -> Min.
+
+%% max(L) -> returns the maximum element of the list L
+
+max_1([H|T]) -> max_1(T, H).
+
+max_1([H|T], Max) when H > Max -> max_1(T, H);
+max_1([_|T], Max) -> max_1(T, Max);
+max_1([], Max) -> Max.
+
+%% sublist(List, Start, Length)
+%% Returns the sub-list starting at Start of length Length.
+
+sublist_1(List, S, L) when L >= 0 ->
+ sublist_1(nthtail_1(S-1, List), L).
+
+sublist_1([H|T], L) when L > 0 ->
+ [H|sublist_1(T, L-1)];
+sublist_1(List, L) -> [].
+
+%% delete(Item, List) -> List'
+%% Delete the first occurance of Item from the list L.
+
+delete_1(Item, [Item|Rest]) -> Rest;
+delete_1(Item, [H|Rest]) ->
+ [H|delete_1(Item, Rest)];
+delete_1(Item, []) -> [].
+
+%% sort(L) -> sorts the list L
+
+sort_1([X]) -> [X];
+sort_1([]) -> [];
+sort_1(X) -> split_and_sort_1(X, [], []).
+
+split_and_sort_1([A,B|T], X, Y) ->
+ split_and_sort_1(T, [A|X], [B|Y]);
+split_and_sort_1([H], X, Y) ->
+ split_and_sort_1([], [H|X], Y);
+split_and_sort_1([], X, Y) ->
+ merge_1(sort_1(X), sort_1(Y), []).
+
+%% merge(X, Y) -> L
+%% merges two sorted lists X and Y
+
+merge_1(X, Y) -> merge_1(X, Y, []).
+
+merge_1([H1|T1], [H2|T2], L) when H1 < H2 ->
+ merge_1(T1, [H2|T2], [H1|L]);
+merge_1(T1, [H2|T2], L) ->
+ merge_1(T1, T2, [H2|L]);
+merge_1([H|T], T2, L) ->
+ merge_1(T, T2, [H|L]);
+merge_1([], [], L) ->
+ reverse_1(L).
+
+%% concat(L) concatinate the list representation of the elements
+%% in L - the elements in L can be atoms, integers of strings.
+%% Returns a list of characters.
+
+concat_1(List) ->
+ flatmap_1(fun thing_to_list/1, List).
+
+thing_to_list_1(X) when integer(X) -> integer_to_list(X);
+thing_to_list_1(X) when float(X) -> float_to_list(X);
+thing_to_list_1(X) when atom(X) -> atom_to_list(X);
+thing_to_list_1(X) when list(X) -> X. %Assumed to be a string
+
+%% flatten(List)
+%% flatten(List, Tail)
+%% Flatten a list, adding optional tail.
+
+flatten_1(List) ->
+ flatten_1(List, [], []).
+
+flatten_1(List, Tail) ->
+ flatten_1(List, [], Tail).
+
+flatten_1([H|T], Cont, Tail) when list(H) ->
+ flatten_1(H, [T|Cont], Tail);
+flatten_1([H|T], Cont, Tail) ->
+ [H|flatten_1(T, Cont, Tail)];
+flatten_1([], [H|Cont], Tail) ->
+ flatten_1(H, Cont, Tail);
+flatten_1([], [], Tail) ->
+ Tail.
+
+%% flat_length(List) (undocumented can be rmove later)
+%% Calculate the length of a list of lists.
+
+flat_length_1(List) -> flatlength_1(List).
+
+%% flatlength(List)
+%% Calculate the length of a list of lists.
+
+flatlength_1(List) ->
+ flatlength_1(List, 0).
+
+flatlength_1([H|T], L) when list(H) ->
+ flatlength_1(H, flatlength_1(T, L));
+flatlength_1([H|T], L) ->
+ flatlength_1(T, L + 1);
+flatlength_1([], L) -> L.
+
+%% keymember(Key, Index, [Tuple])
+%% keysearch(Key, Index, [Tuple])
+%% keydelete(Key, Index, [Tuple])
+%% keyreplace(Key, Index, [Tuple], NewTuple)
+%% keysort(Index, [Tuple])
+%% keymerge(Index, [Tuple], [Tuple])
+%% keymap(Function, Index, [Tuple])
+%% keymap(Function, ExtraArgs, Index, [Tuple])
+
+keymember_1(Key, N, [T|Ts]) when element(N, T) == Key -> true;
+keymember_1(Key, N, [T|Ts]) ->
+ keymember_1(Key, N, Ts);
+keymember_1(Key, N, []) -> false.
+
+keysearch_1(Key, N, [H|T]) when element(N, H) == Key ->
+ {value, H};
+keysearch_1(Key, N, [H|T]) ->
+ keysearch_1(Key, N, T);
+keysearch_1(Key, N, []) -> false.
+
+keydelete_1(Key, N, [H|T]) when element(N, H) == Key -> T;
+keydelete_1(Key, N, [H|T]) ->
+ [H|keydelete_1(Key, N, T)];
+keydelete_1(Key, N, []) -> [].
+
+keyreplace_1(Key, Pos, [Tup|Tail], New) when element(Pos, Tup) == Key ->
+ [New|Tail];
+keyreplace_1(Key, Pos, [H|T], New) ->
+ [H|keyreplace_1(Key, Pos, T, New)];
+keyreplace_1(Key, Pos, [], New) -> [].
+
+keysort_1(Index, [X]) -> [X];
+keysort_1(Index, []) -> [];
+keysort_1(Index, X) -> split_and_keysort_1(X, [], [], Index).
+
+split_and_keysort_1([A,B|T], X, Y, Index) ->
+ split_and_keysort_1(T, [A|X], [B|Y], Index);
+split_and_keysort_1([H], X, Y, Index) ->
+ split_and_keysort_1([], [H|X], Y, Index);
+split_and_keysort_1([], X, Y, Index) ->
+ keymerge_1(Index, keysort_1(Index, X), keysort_1(Index, Y), []).
+
+keymerge_1(Index, X, Y) -> keymerge_1(Index, X, Y, []).
+
+keymerge_1(I, [H1|T1], [H2|T2], L) when element(I, H1) < element(I, H2) ->
+ keymerge_1(I, T1, [H2|T2], [H1|L]);
+keymerge_1(Index, T1, [H2|T2], L) ->
+ keymerge_1(Index,T1, T2, [H2|L]);
+keymerge_1(Index,[H|T], T2, L) ->
+ keymerge_1(Index,T, T2, [H|L]);
+keymerge_1(Index, [], [], L) ->
+ reverse_1(L).
+
+keymap_1(Fun, Index, [Tup|Tail]) ->
+ [setelement(Index, Tup, Fun(element(Index, Tup)))|keymap_1(Fun, Index, Tail)];
+keymap_1( _, _ , []) -> [].
+
+keymap_1(Fun, ExtraArgs, Index, [Tup|Tail]) ->
+ [setelement(Index, Tup, apply(Fun, [element(Index, Tup)|ExtraArgs]))|
+ keymap_1(Fun, ExtraArgs, Index, Tail)];
+keymap_1( _, _ , _, []) -> [].
+
+%% all(Predicate, List)
+%% any(Predicate, List)
+%% map(Function, List)
+%% flatmap(Function, List)
+%% foldl(Function, First, List)
+%% foldr(Function, Last, List)
+%% filter(Predicate, List)
+%% zf(Function, List)
+%% mapfoldl(Function, First, List)
+%% mapfoldr(Function, Last, List)
+%% foreach(Function, List)
+%% takewhile(Predicate, List)
+%% dropwhile(Predicate, List)
+%% splitwith(Predicate, List)
+%% for list programming. Function here is either a 'fun' or a tuple
+%% {Module,Name} and we use apply/2 to evaluate. The name zf is a joke!
+%%
+%% N.B. Unless where the functions actually needs it only foreach/2/3,
+%% which is meant to be used for its side effects, has a defined order
+%% of evaluation.
+%%
+%% There are also versions with an extra argument, ExtraArgs, which is a
+%% list of extra arguments to each call.
+
+all_1(Pred, [Hd|Tail]) ->
+ case Pred(Hd) of
+ true -> all_1(Pred, Tail);
+ false -> false
+ end;
+all_1(Pred, []) -> true.
+
+any_1(Pred, [Hd|Tail]) ->
+ case Pred(Hd) of
+ true -> true;
+ false -> any_1(Pred, Tail)
+ end;
+any_1(Pred, []) -> false.
+
+map_1(F, List) -> [ F(E) || E <- List ].
+
+flatmap_1(F, [Hd|Tail]) ->
+ F(Hd) ++ flatmap_1(F, Tail);
+flatmap_1(F, []) -> [].
+
+foldl_1(F, Accu, [Hd|Tail]) ->
+ foldl_1(F, F(Hd, Accu), Tail);
+foldl_1(F, Accu, []) -> Accu.
+
+foldr_1(F, Accu, [Hd|Tail]) ->
+ F(Hd, foldr_1(F, Accu, Tail));
+foldr_1(F, Accu, []) -> Accu.
+
+filter_1(Pred, List) -> [ E || E <- List, Pred(E) ].
+
+zF(F, [Hd|Tail]) ->
+ case F(Hd) of
+ true ->
+ [Hd|zF(F, Tail)];
+ {true,Val} ->
+ [Val|zF(F, Tail)];
+ false ->
+ zF(F, Tail)
+ end;
+zF(F, []) -> [].
+
+foreach_1(F, [Hd|Tail]) ->
+ F(Hd),
+ foreach_1(F, Tail);
+foreach_1(F, []) -> ok.
+
+mapfoldl_1(F, Accu0, [Hd|Tail]) ->
+ {R,Accu1} = F(Hd, Accu0),
+ {Rs,Accu2} = mapfoldl_1(F, Accu1, Tail),
+ {[R|Rs],Accu2};
+mapfoldl_1(F, Accu, []) -> {[],Accu}.
+
+mapfoldr_1(F, Accu0, [Hd|Tail]) ->
+ {Rs,Accu1} = mapfoldr_1(F, Accu0, Tail),
+ {R,Accu2} = F(Hd, Accu1),
+ {[R|Rs],Accu2};
+mapfoldr_1(F, Accu, []) -> {[],Accu}.
+
+takewhile_1(Pred, [Hd|Tail]) ->
+ case Pred(Hd) of
+ true -> [Hd|takewhile_1(Pred, Tail)];
+ false -> []
+ end;
+takewhile_1(Pred, []) -> [].
+
+dropwhile_1(Pred, [Hd|Tail]) ->
+ case Pred(Hd) of
+ true -> dropwhile_1(Pred, Tail);
+ false -> [Hd|Tail]
+ end;
+dropwhile_1(Pred, []) -> [].
+
+splitwith_1(Pred, List) -> splitwith_1(Pred, List, []).
+
+splitwith_1(Pred, [Hd|Tail], Taken) ->
+ case Pred(Hd) of
+ true -> splitwith_1(Pred, Tail, [Hd|Taken]);
+ false -> {reverse_1(Taken), [Hd|Tail]}
+ end;
+splitwith_1(Pred, [], Taken) -> {reverse_1(Taken),[]}.
+
+%% Versions of the above functions with extra arguments.
+
+all_1(Pred, Eas, [Hd|Tail]) ->
+ case apply(Pred, [Hd|Eas]) of
+ true -> all_1(Pred, Eas, Tail);
+ false -> false
+ end;
+all_1(Pred, Eas, []) -> true.
+
+any_1(Pred, Eas, [Hd|Tail]) ->
+ case apply(Pred, [Hd|Eas]) of
+ true -> true;
+ false -> any_1(Pred, Eas, Tail)
+ end;
+any_1(Pred, Eas, []) -> false.
+
+map_1(F, Eas, List) -> [ apply(F, [E|Eas]) || E <- List ].
+
+flatmap_1(F, Eas, [Hd|Tail]) ->
+ apply(F, [Hd|Eas]) ++ flatmap_1(F, Eas, Tail);
+flatmap_1(F, Eas, []) -> [].
+
+foldl_1(F, Eas, Accu, [Hd|Tail]) ->
+ foldl_1(F, Eas, apply(F, [Hd,Accu|Eas]), Tail);
+foldl_1(F, Eas, Accu, []) -> Accu.
+
+foldr_1(F, Eas, Accu, [Hd|Tail]) ->
+ apply(F, [Hd,foldr_1(F, Eas, Accu, Tail)|Eas]);
+foldr_1(F, Eas, Accu, []) ->
+ Accu.
+
+filter_1(Pred, Eas, List) -> [ E || E <- List, apply(Pred, [E|Eas]) ].
+
+zF(F, Eas, [Hd|Tail]) ->
+ case apply(F, [Hd|Eas]) of
+ true ->
+ [Hd|zF(F, Eas, Tail)];
+ {true,Val} ->
+ [Val|zF(F, Eas, Tail)];
+ false ->
+ zF(F, Eas, Tail)
+ end;
+zF(F, Eas, []) -> [].
+
+foreach_1(F, Eas, [Hd|Tail]) ->
+ apply(F, [Hd|Eas]),
+ foreach_1(F, Eas, Tail);
+foreach_1(F, Eas, []) -> ok.
+
+mapfoldl_1(F, Eas, Accu0, [Hd|Tail]) ->
+ {R,Accu1} = apply(F, [Hd,Accu0|Eas]),
+ {Rs,Accu2} = mapfoldl_1(F, Eas, Accu1, Tail),
+ {[R|Rs],Accu2};
+mapfoldl_1(F, Eas, Accu, []) -> {[],Accu}.
+
+mapfoldr_1(F, Eas, Accu0, [Hd|Tail]) ->
+ {Rs,Accu1} = mapfoldr_1(F, Eas, Accu0, Tail),
+ {R,Accu2} = apply(F, [Hd,Accu1|Eas]),
+ {[R|Rs],Accu2};
+mapfoldr_1(F, Eas, Accu, []) -> {[],Accu}.
+
+%% takewhile/2, dropwhile/2 and splitwith/2 do not have versions with
+%% extra arguments as this going to be discontinued.
+
+
+
+
+
+
+%%% +++++++++++++++++++++
+%%%
+%%% "_2"
+
+
+
+
+
+%% member_2(X, L) -> _2(true | false)
+%% test if X is a member of the list L
+
+%member_2(X, [X|_]) -> true;
+%member_2(X, [_|Y]) ->
+% member_2(X, Y);
+%member_2(X, []) -> false.
+
+member_2(X, L) when list(L) ->
+ case erlang:member_2(X, L) of
+ L1 when list(L1) ->
+ receive after 1 -> ok end,
+ member_2(X, L1);
+ Boolean ->
+ Boolean
+ end.
+
+%% append_2(X, Y) appends lists X and Y
+
+append_2(L1, L2) -> L1 ++ L2.
+
+%% append_2(L) appends the list of lists L
+
+append_2([E]) -> E;
+append_2([H|T]) -> H ++ append_2(T);
+append_2([]) -> [].
+
+%% subtract_2(List1, List2) subtract elements in List2 form List1.
+
+subtract_2(L1, L2) -> L1 -- L2.
+
+%% reverse_2(L) reverse all elements in the list L
+
+reverse_2(X) -> reverse_2(X, []).
+
+%reverse_2([H|T], Y) ->
+% reverse_2(T, [H|Y]);
+%reverse_2([], X) -> X.
+
+reverse_2(List0, Result0) when list(List0) ->
+ case erlang:reverse_2(List0, Result0) of
+ {List, Result} ->
+ receive after 1 -> ok end,
+ reverse_2(List, Result);
+ Result ->
+ Result
+ end.
+
+
+%% nth_2(N, L) returns the N`th element of the list L
+%% nthtail_2(N, L) returns the N`th tail of the list L
+
+nth_2(1, [H|T]) -> H;
+nth_2(N, [_|T]) when N > 1 ->
+ nth_2(N - 1, T).
+
+nthtail_2(1, [H|T]) -> T;
+nthtail_2(N, [H|T]) when N > 1 ->
+ nthtail_2(N - 1, T);
+nthtail_2(0, L) when list(L) -> L.
+
+%% prefix_2(Prefix, List) -> _2(true | false)
+
+prefix_2([X|PreTail], [X|Tail]) ->
+ prefix_2(PreTail, Tail);
+prefix_2([], List) -> true;
+prefix_2(_,_) -> false.
+
+
+%% suffix_2(Suffix, List) -> _2(true | false)
+
+suffix_2(Suffix, Suffix) -> true;
+suffix_2(Suffix, [_|Tail]) ->
+ suffix_2(Suffix, Tail);
+suffix_2(Suffix, []) -> false.
+
+%% last_2(List) returns the last element in a list.
+
+last_2([E]) -> E;
+last_2([E|Es]) ->
+ last_2(Es).
+
+%% seq_2(Min, Max) -> [Min,Min+1, ..., Max]
+%% seq_2(Min, Max, Incr) -> [Min,Min+Incr, ..., Max]
+%% returns the sequence Min..Max
+%% Min <= Max and Min and Max must be integers
+
+seq_2(Min, Max) when integer(Min), integer(Max), Min =< Max ->
+ seq_2(Min, Max, 1, []).
+
+seq_2(Min, Max, Incr) ->
+ seq_2(Min, Min + ((Max-Min) div Incr) * Incr, Incr, []).
+
+seq_2(Min, Min, I, L) -> [Min|L];
+seq_2(Min, Max, I, L) -> seq_2(Min, Max-I, I, [Max|L]).
+
+%% sum_2(L) suns the sum of the elements in L
+
+sum_2(L) -> sum_2(L, 0).
+sum_2([H|T], Sum) -> sum_2(T, Sum + H);
+sum_2([], Sum) -> Sum.
+
+%% duplicate_2(N, X) -> [X,X,X,.....,X] _2(N times)
+%% return N copies of X
+
+duplicate_2(N, X) when integer(N), N >= 0 -> duplicate_2(N, X, []).
+
+duplicate_2(0, _, L) -> L;
+duplicate_2(N, X, L) -> duplicate_2(N-1, X, [X|L]).
+
+
+%% min_2(L) -> returns the minimum element of the list L
+
+min_2([H|T]) -> min_2(T, H).
+
+min_2([H|T], Min) when H < Min -> min_2(T, H);
+min_2([_|T], Min) -> min_2(T, Min);
+min_2([], Min) -> Min.
+
+%% max_2(L) -> returns the maximum element of the list L
+
+max_2([H|T]) -> max_2(T, H).
+
+max_2([H|T], Max) when H > Max -> max_2(T, H);
+max_2([_|T], Max) -> max_2(T, Max);
+max_2([], Max) -> Max.
+
+%% sublist(List, Start, Length)
+%% Returns the sub-list starting at Start of length Length.
+
+sublist_2(List, S, L) when L >= 0 ->
+ sublist_2(nthtail_2(S-1, List), L).
+
+sublist_2([H|T], L) when L > 0 ->
+ [H|sublist_2(T, L-1)];
+sublist_2(List, L) -> [].
+
+%% delete_2(Item, List) -> List'
+%% Delete the first occurance of Item from the list L.
+
+delete_2(Item, [Item|Rest]) -> Rest;
+delete_2(Item, [H|Rest]) ->
+ [H|delete_2(Item, Rest)];
+delete_2(Item, []) -> [].
+
+%% sort_2(L) -> sorts the list L
+
+sort_2([X]) -> [X];
+sort_2([]) -> [];
+sort_2(X) -> split_and_sort_2(X, [], []).
+
+split_and_sort_2([A,B|T], X, Y) ->
+ split_and_sort_2(T, [A|X], [B|Y]);
+split_and_sort_2([H], X, Y) ->
+ split_and_sort_2([], [H|X], Y);
+split_and_sort_2([], X, Y) ->
+ merge_2(sort_2(X), sort_2(Y), []).
+
+%% merge_2(X, Y) -> L
+%% merges two sorted lists X and Y
+
+merge_2(X, Y) -> merge_2(X, Y, []).
+
+merge_2([H1|T1], [H2|T2], L) when H1 < H2 ->
+ merge_2(T1, [H2|T2], [H1|L]);
+merge_2(T1, [H2|T2], L) ->
+ merge_2(T1, T2, [H2|L]);
+merge_2([H|T], T2, L) ->
+ merge_2(T, T2, [H|L]);
+merge_2([], [], L) ->
+ reverse_2(L).
+
+%% concat_2(L) concatinate the list representation of the elements
+%% in L - the elements in L can be atoms, integers of strings.
+%% Returns a list of characters.
+
+concat_2(List) ->
+ flatmap_2(fun thing_to_list/1, List).
+
+thing_to_list_2(X) when integer(X) -> integer_to_list(X);
+thing_to_list_2(X) when float(X) -> float_to_list(X);
+thing_to_list_2(X) when atom(X) -> atom_to_list(X);
+thing_to_list_2(X) when list(X) -> X. %Assumed to be a string
+
+%% flatten_2(List)
+%% flatten_2(List, Tail)
+%% Flatten a list, adding optional tail.
+
+flatten_2(List) ->
+ flatten_2(List, [], []).
+
+flatten_2(List, Tail) ->
+ flatten_2(List, [], Tail).
+
+flatten_2([H|T], Cont, Tail) when list(H) ->
+ flatten_2(H, [T|Cont], Tail);
+flatten_2([H|T], Cont, Tail) ->
+ [H|flatten_2(T, Cont, Tail)];
+flatten_2([], [H|Cont], Tail) ->
+ flatten_2(H, Cont, Tail);
+flatten_2([], [], Tail) ->
+ Tail.
+
+%% flat_length_2(List) _2(undocumented can be rmove later)
+%% Calculate the length of a list of lists.
+
+flat_length_2(List) -> flatlength_2(List).
+
+%% flatlength_2(List)
+%% Calculate the length of a list of lists.
+
+flatlength_2(List) ->
+ flatlength_2(List, 0).
+
+flatlength_2([H|T], L) when list(H) ->
+ flatlength_2(H, flatlength_2(T, L));
+flatlength_2([H|T], L) ->
+ flatlength_2(T, L + 1);
+flatlength_2([], L) -> L.
+
+%% keymember_2(Key, Index, [Tuple])
+%% keysearch_2(Key, Index, [Tuple])
+%% keydelete_2(Key, Index, [Tuple])
+%% keyreplace_2(Key, Index, [Tuple], NewTuple)
+%% keysort_2(Index, [Tuple])
+%% keymerge_2(Index, [Tuple], [Tuple])
+%% keymap_2(Function, Index, [Tuple])
+%% keymap_2(Function, ExtraArgs, Index, [Tuple])
+
+keymember_2(Key, N, [T|Ts]) when element(N, T) == Key -> true;
+keymember_2(Key, N, [T|Ts]) ->
+ keymember_2(Key, N, Ts);
+keymember_2(Key, N, []) -> false.
+
+keysearch_2(Key, N, [H|T]) when element(N, H) == Key ->
+ {value, H};
+keysearch_2(Key, N, [H|T]) ->
+ keysearch_2(Key, N, T);
+keysearch_2(Key, N, []) -> false.
+
+keydelete_2(Key, N, [H|T]) when element(N, H) == Key -> T;
+keydelete_2(Key, N, [H|T]) ->
+ [H|keydelete_2(Key, N, T)];
+keydelete_2(Key, N, []) -> [].
+
+keyreplace_2(Key, Pos, [Tup|Tail], New) when element(Pos, Tup) == Key ->
+ [New|Tail];
+keyreplace_2(Key, Pos, [H|T], New) ->
+ [H|keyreplace_2(Key, Pos, T, New)];
+keyreplace_2(Key, Pos, [], New) -> [].
+
+keysort_2(Index, [X]) -> [X];
+keysort_2(Index, []) -> [];
+keysort_2(Index, X) -> split_and_keysort_2(X, [], [], Index).
+
+split_and_keysort_2([A,B|T], X, Y, Index) ->
+ split_and_keysort_2(T, [A|X], [B|Y], Index);
+split_and_keysort_2([H], X, Y, Index) ->
+ split_and_keysort_2([], [H|X], Y, Index);
+split_and_keysort_2([], X, Y, Index) ->
+ keymerge_2(Index, keysort_2(Index, X), keysort_2(Index, Y), []).
+
+keymerge_2(Index, X, Y) -> keymerge_2(Index, X, Y, []).
+
+keymerge_2(I, [H1|T1], [H2|T2], L) when element(I, H1) < element(I, H2) ->
+ keymerge_2(I, T1, [H2|T2], [H1|L]);
+keymerge_2(Index, T1, [H2|T2], L) ->
+ keymerge_2(Index,T1, T2, [H2|L]);
+keymerge_2(Index,[H|T], T2, L) ->
+ keymerge_2(Index,T, T2, [H|L]);
+keymerge_2(Index, [], [], L) ->
+ reverse_2(L).
+
+keymap_2(Fun, Index, [Tup|Tail]) ->
+ [setelement(Index, Tup, Fun(element(Index, Tup)))|keymap_2(Fun, Index, Tail)];
+keymap_2( _, _ , []) -> [].
+
+keymap_2(Fun, ExtraArgs, Index, [Tup|Tail]) ->
+ [setelement(Index, Tup, apply(Fun, [element(Index, Tup)|ExtraArgs]))|
+ keymap_2(Fun, ExtraArgs, Index, Tail)];
+keymap_2( _, _ , _, []) -> [].
+
+%% all_2(Predicate, List)
+%% any_2(Predicate, List)
+%% map_2(Function, List)
+%% flatmap_2(Function, List)
+%% foldl_2(Function, First, List)
+%% foldr_2(Function, Last, List)
+%% filter_2(Predicate, List)
+%% zF(Function, List)
+%% mapfoldl_2(Function, First, List)
+%% mapfoldr_2(Function, Last, List)
+%% foreach_2(Function, List)
+%% takewhile_2(Predicate, List)
+%% dropwhile_2(Predicate, List)
+%% splitwith_2(Predicate, List)
+%% for list programming. Function here is either a 'fun' or a tuple
+%% {Module,Name} and we use apply/2 to evaluate. The name zf is a joke!
+%%
+%% N.B. Unless where the functions actually needs it only foreach/2/3,
+%% which is meant to be used for its side effects, has a defined order
+%% of evaluation.
+%%
+%% There are also versions with an extra argument, ExtraArgs, which is a
+%% list of extra arguments to each call.
+
+all_2(Pred, [Hd|Tail]) ->
+ case Pred(Hd) of
+ true -> all_2(Pred, Tail);
+ false -> false
+ end;
+all_2(Pred, []) -> true.
+
+any_2(Pred, [Hd|Tail]) ->
+ case Pred(Hd) of
+ true -> true;
+ false -> any_2(Pred, Tail)
+ end;
+any_2(Pred, []) -> false.
+
+map_2(F, List) -> [ F(E) || E <- List ].
+
+flatmap_2(F, [Hd|Tail]) ->
+ F(Hd) ++ flatmap_2(F, Tail);
+flatmap_2(F, []) -> [].
+
+foldl_2(F, Accu, [Hd|Tail]) ->
+ foldl_2(F, F(Hd, Accu), Tail);
+foldl_2(F, Accu, []) -> Accu.
+
+foldr_2(F, Accu, [Hd|Tail]) ->
+ F(Hd, foldr_2(F, Accu, Tail));
+foldr_2(F, Accu, []) -> Accu.
+
+filter_2(Pred, List) -> [ E || E <- List, Pred(E) ].
+
+zF_2(F, [Hd|Tail]) ->
+ case F(Hd) of
+ true ->
+ [Hd|zF_2(F, Tail)];
+ {true,Val} ->
+ [Val|zF_2(F, Tail)];
+ false ->
+ zF_2(F, Tail)
+ end;
+zF_2(F, []) -> [].
+
+foreach_2(F, [Hd|Tail]) ->
+ F(Hd),
+ foreach_2(F, Tail);
+foreach_2(F, []) -> ok.
+
+mapfoldl_2(F, Accu0, [Hd|Tail]) ->
+ {R,Accu1} = F(Hd, Accu0),
+ {Rs,Accu2} = mapfoldl_2(F, Accu1, Tail),
+ {[R|Rs],Accu2};
+mapfoldl_2(F, Accu, []) -> {[],Accu}.
+
+mapfoldr_2(F, Accu0, [Hd|Tail]) ->
+ {Rs,Accu1} = mapfoldr_2(F, Accu0, Tail),
+ {R,Accu2} = F(Hd, Accu1),
+ {[R|Rs],Accu2};
+mapfoldr_2(F, Accu, []) -> {[],Accu}.
+
+takewhile_2(Pred, [Hd|Tail]) ->
+ case Pred(Hd) of
+ true -> [Hd|takewhile_2(Pred, Tail)];
+ false -> []
+ end;
+takewhile_2(Pred, []) -> [].
+
+dropwhile_2(Pred, [Hd|Tail]) ->
+ case Pred(Hd) of
+ true -> dropwhile_2(Pred, Tail);
+ false -> [Hd|Tail]
+ end;
+dropwhile_2(Pred, []) -> [].
+
+splitwith_2(Pred, List) -> splitwith_2(Pred, List, []).
+
+splitwith_2(Pred, [Hd|Tail], Taken) ->
+ case Pred(Hd) of
+ true -> splitwith_2(Pred, Tail, [Hd|Taken]);
+ false -> {reverse_2(Taken), [Hd|Tail]}
+ end;
+splitwith_2(Pred, [], Taken) -> {reverse_2(Taken),[]}.
+
+%% Versions of the above functions with extra arguments.
+
+all_2(Pred, Eas, [Hd|Tail]) ->
+ case apply(Pred, [Hd|Eas]) of
+ true -> all_2(Pred, Eas, Tail);
+ false -> false
+ end;
+all_2(Pred, Eas, []) -> true.
+
+any_2(Pred, Eas, [Hd|Tail]) ->
+ case apply(Pred, [Hd|Eas]) of
+ true -> true;
+ false -> any_2(Pred, Eas, Tail)
+ end;
+any_2(Pred, Eas, []) -> false.
+
+map_2(F, Eas, List) -> [ apply(F, [E|Eas]) || E <- List ].
+
+flatmap_2(F, Eas, [Hd|Tail]) ->
+ apply(F, [Hd|Eas]) ++ flatmap_2(F, Eas, Tail);
+flatmap_2(F, Eas, []) -> [].
+
+foldl_2(F, Eas, Accu, [Hd|Tail]) ->
+ foldl_2(F, Eas, apply(F, [Hd,Accu|Eas]), Tail);
+foldl_2(F, Eas, Accu, []) -> Accu.
+
+foldr_2(F, Eas, Accu, [Hd|Tail]) ->
+ apply(F, [Hd,foldr_2(F, Eas, Accu, Tail)|Eas]);
+foldr_2(F, Eas, Accu, []) ->
+ Accu.
+
+filter_2(Pred, Eas, List) -> [ E || E <- List, apply(Pred, [E|Eas]) ].
+
+zF_2(F, Eas, [Hd|Tail]) ->
+ case apply(F, [Hd|Eas]) of
+ true ->
+ [Hd|zF_2(F, Eas, Tail)];
+ {true,Val} ->
+ [Val|zF_2(F, Eas, Tail)];
+ false ->
+ zF_2(F, Eas, Tail)
+ end;
+zF_2(F, Eas, []) -> [].
+
+foreach_2(F, Eas, [Hd|Tail]) ->
+ apply(F, [Hd|Eas]),
+ foreach_2(F, Eas, Tail);
+foreach_2(F, Eas, []) -> ok.
+
+mapfoldl_2(F, Eas, Accu0, [Hd|Tail]) ->
+ {R,Accu1} = apply(F, [Hd,Accu0|Eas]),
+ {Rs,Accu2} = mapfoldl_2(F, Eas, Accu1, Tail),
+ {[R|Rs],Accu2};
+mapfoldl_2(F, Eas, Accu, []) -> {[],Accu}.
+
+mapfoldr_2(F, Eas, Accu0, [Hd|Tail]) ->
+ {Rs,Accu1} = mapfoldr_2(F, Eas, Accu0, Tail),
+ {R,Accu2} = apply(F, [Hd,Accu1|Eas]),
+ {[R|Rs],Accu2};
+mapfoldr_2(F, Eas, Accu, []) -> {[],Accu}.
+
+%% takewhile/2, dropwhile/2 and splitwith/2 do not have versions with
+%% extra arguments as this going to be discontinued.
+
+
+
+
+
+%%% +++++++++++++++++++
+%%%
+%%% With "_3"
+
+
+
+
+%% member_3(X, L) -> _3(true | false)
+%% test if X is a member of the list L
+
+%member_3(X, [X|_]) -> true;
+%member_3(X, [_|Y]) ->
+% member_3(X, Y);
+%member_3(X, []) -> false.
+
+member_3(X, L) when list(L) ->
+ case erlang:member(X, L) of
+ L1 when list(L1) ->
+ receive after 1 -> ok end,
+ member_3(X, L1);
+ Boolean ->
+ Boolean
+ end.
+
+%% append_3(X, Y) appends lists X and Y
+
+append_3(L1, L2) -> L1 ++ L2.
+
+%% append_3(L) appends the list of lists L
+
+append_3([E]) -> E;
+append_3([H|T]) -> H ++ append_3(T);
+append_3([]) -> [].
+
+%% subtract_3(List1, List2) subtract elements in List2 form List1.
+
+subtract_3(L1, L2) -> L1 -- L2.
+
+%% reverse_3(L) reverse all elements in the list L
+
+reverse_3(X) -> reverse_3(X, []).
+
+%reverse_3([H|T], Y) ->
+% reverse_3(T, [H|Y]);
+%reverse_3([], X) -> X.
+
+reverse_3(List0, Result0) when list(List0) ->
+ case erlang:reverse_3(List0, Result0) of
+ {List, Result} ->
+ receive after 1 -> ok end,
+ reverse_3(List, Result);
+ Result ->
+ Result
+ end.
+
+
+%% nth_3(N, L) returns the N`th element of the list L
+%% nthtail_3(N, L) returns the N`th tail of the list L
+
+nth_3(1, [H|T]) -> H;
+nth_3(N, [_|T]) when N > 1 ->
+ nth_3(N - 1, T).
+
+nthtail_3(1, [H|T]) -> T;
+nthtail_3(N, [H|T]) when N > 1 ->
+ nthtail_3(N - 1, T);
+nthtail_3(0, L) when list(L) -> L.
+
+%% prefix_3(Prefix, List) -> _3(true | false)
+
+prefix_3([X|PreTail], [X|Tail]) ->
+ prefix_3(PreTail, Tail);
+prefix_3([], List) -> true;
+prefix_3(_,_) -> false.
+
+
+%% suffix_3(Suffix, List) -> _3(true | false)
+
+suffix_3(Suffix, Suffix) -> true;
+suffix_3(Suffix, [_|Tail]) ->
+ suffix_3(Suffix, Tail);
+suffix_3(Suffix, []) -> false.
+
+%% last_3(List) returns the last element in a list.
+
+last_3([E]) -> E;
+last_3([E|Es]) ->
+ last_3(Es).
+
+%% seq_3(Min, Max) -> [Min,Min+1, ..., Max]
+%% seq_3(Min, Max, Incr) -> [Min,Min+Incr, ..., Max]
+%% returns the sequence Min..Max
+%% Min <= Max and Min and Max must be integers
+
+seq_3(Min, Max) when integer(Min), integer(Max), Min =< Max ->
+ seq_3(Min, Max, 1, []).
+
+seq_3(Min, Max, Incr) ->
+ seq_3(Min, Min + ((Max-Min) div Incr) * Incr, Incr, []).
+
+seq_3(Min, Min, I, L) -> [Min|L];
+seq_3(Min, Max, I, L) -> seq_3(Min, Max-I, I, [Max|L]).
+
+%% sum_3(L) suns the sum of the elements in L
+
+sum_3(L) -> sum_3(L, 0).
+sum_3([H|T], Sum) -> sum_3(T, Sum + H);
+sum_3([], Sum) -> Sum.
+
+%% duplicate_3(N, X) -> [X,X,X,.....,X] _3(N times)
+%% return N copies of X
+
+duplicate_3(N, X) when integer(N), N >= 0 -> duplicate_3(N, X, []).
+
+duplicate_3(0, _, L) -> L;
+duplicate_3(N, X, L) -> duplicate_3(N-1, X, [X|L]).
+
+
+%% min_3(L) -> returns the minimum element of the list L
+
+min_3([H|T]) -> min_3(T, H).
+
+min_3([H|T], Min) when H < Min -> min_3(T, H);
+min_3([_|T], Min) -> min_3(T, Min);
+min_3([], Min) -> Min.
+
+%% max_3(L) -> returns the maximum element of the list L
+
+max_3([H|T]) -> max_3(T, H).
+
+max_3([H|T], Max) when H > Max -> max_3(T, H);
+max_3([_|T], Max) -> max_3(T, Max);
+max_3([], Max) -> Max.
+
+%% sublist_3(List, Start, Length)
+%% Returns the sub-list starting at Start of length Length.
+
+sublist_3(List, S, L) when L >= 0 ->
+ sublist_3(nthtail_3(S-1, List), L).
+
+sublist_3([H|T], L) when L > 0 ->
+ [H|sublist_3(T, L-1)];
+sublist_3(List, L) -> [].
+
+%% delete_3(Item, List) -> List'
+%% Delete the first occurance of Item from the list L.
+
+delete_3(Item, [Item|Rest]) -> Rest;
+delete_3(Item, [H|Rest]) ->
+ [H|delete_3(Item, Rest)];
+delete_3(Item, []) -> [].
+
+%% sort_3(L) -> sorts the list L
+
+sort_3([X]) -> [X];
+sort_3([]) -> [];
+sort_3(X) -> split_and_sort_3(X, [], []).
+
+split_and_sort_3([A,B|T], X, Y) ->
+ split_and_sort_3(T, [A|X], [B|Y]);
+split_and_sort_3([H], X, Y) ->
+ split_and_sort_3([], [H|X], Y);
+split_and_sort_3([], X, Y) ->
+ merge_3(sort_3(X), sort_3(Y), []).
+
+%% merge_3(X, Y) -> L
+%% merges two sorted lists X and Y
+
+merge_3(X, Y) -> merge_3(X, Y, []).
+
+merge_3([H1|T1], [H2|T2], L) when H1 < H2 ->
+ merge_3(T1, [H2|T2], [H1|L]);
+merge_3(T1, [H2|T2], L) ->
+ merge_3(T1, T2, [H2|L]);
+merge_3([H|T], T2, L) ->
+ merge_3(T, T2, [H|L]);
+merge_3([], [], L) ->
+ reverse_3(L).
+
+%% concat_3(L) concatinate the list representation of the elements
+%% in L - the elements in L can be atoms, integers of strings.
+%% Returns a list of characters.
+
+concat_3(List) ->
+ flatmap_3(fun thing_to_list/1, List).
+
+thing_to_list_3(X) when integer(X) -> integer_to_list(X);
+thing_to_list_3(X) when float(X) -> float_to_list(X);
+thing_to_list_3(X) when atom(X) -> atom_to_list(X);
+thing_to_list_3(X) when list(X) -> X. %Assumed to be a string
+
+%% flatten_3(List)
+%% flatten_3(List, Tail)
+%% Flatten a list, adding optional tail.
+
+flatten_3(List) ->
+ flatten_3(List, [], []).
+
+flatten_3(List, Tail) ->
+ flatten_3(List, [], Tail).
+
+flatten_3([H|T], Cont, Tail) when list(H) ->
+ flatten_3(H, [T|Cont], Tail);
+flatten_3([H|T], Cont, Tail) ->
+ [H|flatten_3(T, Cont, Tail)];
+flatten_3([], [H|Cont], Tail) ->
+ flatten_3(H, Cont, Tail);
+flatten_3([], [], Tail) ->
+ Tail.
+
+%% flat_length_3(List) _3(undocumented can be rmove later)
+%% Calculate the length of a list of lists.
+
+flat_length_3(List) -> flatlength_3(List).
+
+%% flatlength_3(List)
+%% Calculate the length of a list of lists.
+
+flatlength_3(List) ->
+ flatlength_3(List, 0).
+
+flatlength_3([H|T], L) when list(H) ->
+ flatlength_3(H, flatlength_3(T, L));
+flatlength_3([H|T], L) ->
+ flatlength_3(T, L + 1);
+flatlength_3([], L) -> L.
+
+%% keymember_3(Key, Index, [Tuple])
+%% keysearch_3(Key, Index, [Tuple])
+%% keydelete_3(Key, Index, [Tuple])
+%% keyreplace_3(Key, Index, [Tuple], NewTuple)
+%% keysort_3(Index, [Tuple])
+%% keymerge_3(Index, [Tuple], [Tuple])
+%% keymap_3(Function, Index, [Tuple])
+%% keymap_3(Function, ExtraArgs, Index, [Tuple])
+
+keymember_3(Key, N, [T|Ts]) when element(N, T) == Key -> true;
+keymember_3(Key, N, [T|Ts]) ->
+ keymember_3(Key, N, Ts);
+keymember_3(Key, N, []) -> false.
+
+keysearch_3(Key, N, [H|T]) when element(N, H) == Key ->
+ {value, H};
+keysearch_3(Key, N, [H|T]) ->
+ keysearch_3(Key, N, T);
+keysearch_3(Key, N, []) -> false.
+
+keydelete_3(Key, N, [H|T]) when element(N, H) == Key -> T;
+keydelete_3(Key, N, [H|T]) ->
+ [H|keydelete_3(Key, N, T)];
+keydelete_3(Key, N, []) -> [].
+
+keyreplace_3(Key, Pos, [Tup|Tail], New) when element(Pos, Tup) == Key ->
+ [New|Tail];
+keyreplace_3(Key, Pos, [H|T], New) ->
+ [H|keyreplace_3(Key, Pos, T, New)];
+keyreplace_3(Key, Pos, [], New) -> [].
+
+keysort_3(Index, [X]) -> [X];
+keysort_3(Index, []) -> [];
+keysort_3(Index, X) -> split_and_keysort_3(X, [], [], Index).
+
+split_and_keysort_3([A,B|T], X, Y, Index) ->
+ split_and_keysort_3(T, [A|X], [B|Y], Index);
+split_and_keysort_3([H], X, Y, Index) ->
+ split_and_keysort_3([], [H|X], Y, Index);
+split_and_keysort_3([], X, Y, Index) ->
+ keymerge_3(Index, keysort_3(Index, X), keysort_3(Index, Y), []).
+
+keymerge_3(Index, X, Y) -> keymerge_3(Index, X, Y, []).
+
+keymerge_3(I, [H1|T1], [H2|T2], L) when element(I, H1) < element(I, H2) ->
+ keymerge_3(I, T1, [H2|T2], [H1|L]);
+keymerge_3(Index, T1, [H2|T2], L) ->
+ keymerge_3(Index,T1, T2, [H2|L]);
+keymerge_3(Index,[H|T], T2, L) ->
+ keymerge_3(Index,T, T2, [H|L]);
+keymerge_3(Index, [], [], L) ->
+ reverse_3(L).
+
+keymap_3(Fun, Index, [Tup|Tail]) ->
+ [setelement(Index, Tup, Fun(element(Index, Tup)))|keymap_3(Fun, Index, Tail)];
+keymap_3( _, _ , []) -> [].
+
+keymap_3(Fun, ExtraArgs, Index, [Tup|Tail]) ->
+ [setelement(Index, Tup, apply(Fun, [element(Index, Tup)|ExtraArgs]))|
+ keymap_3(Fun, ExtraArgs, Index, Tail)];
+keymap_3( _, _ , _, []) -> [].
+
+%% all_3(Predicate, List)
+%% any_3(Predicate, List)
+%% map_3(Function, List)
+%% flatmap_3(Function, List)
+%% foldl_3(Function, First, List)
+%% foldr_3(Function, Last, List)
+%% filter_3(Predicate, List)
+%% zF(Function, List)
+%% mapfoldl_3(Function, First, List)
+%% mapfoldr_3(Function, Last, List)
+%% foreach_3(Function, List)
+%% takewhile_3(Predicate, List)
+%% dropwhile_3(Predicate, List)
+%% splitwith_3(Predicate, List)
+%% for list programming. Function here is either a 'fun' or a tuple
+%% {Module,Name} and we use apply/2 to evaluate. The name zf is a joke!
+%%
+%% N.B. Unless where the functions actually needs it only foreach/2/3,
+%% which is meant to be used for its side effects, has a defined order
+%% of evaluation.
+%%
+%% There are also versions with an extra argument, ExtraArgs, which is a
+%% list of extra arguments to each call.
+
+all_3(Pred, [Hd|Tail]) ->
+ case Pred(Hd) of
+ true -> all_3(Pred, Tail);
+ false -> false
+ end;
+all_3(Pred, []) -> true.
+
+any_3(Pred, [Hd|Tail]) ->
+ case Pred(Hd) of
+ true -> true;
+ false -> any_3(Pred, Tail)
+ end;
+any_3(Pred, []) -> false.
+
+map_3(F, List) -> [ F(E) || E <- List ].
+
+flatmap_3(F, [Hd|Tail]) ->
+ F(Hd) ++ flatmap_3(F, Tail);
+flatmap_3(F, []) -> [].
+
+foldl_3(F, Accu, [Hd|Tail]) ->
+ foldl_3(F, F(Hd, Accu), Tail);
+foldl_3(F, Accu, []) -> Accu.
+
+foldr_3(F, Accu, [Hd|Tail]) ->
+ F(Hd, foldr_3(F, Accu, Tail));
+foldr_3(F, Accu, []) -> Accu.
+
+filter_3(Pred, List) -> [ E || E <- List, Pred(E) ].
+
+zF_3(F, [Hd|Tail]) ->
+ case F(Hd) of
+ true ->
+ [Hd|zF_3(F, Tail)];
+ {true,Val} ->
+ [Val|zF_3(F, Tail)];
+ false ->
+ zF_3(F, Tail)
+ end;
+zF_3(F, []) -> [].
+
+foreach_3(F, [Hd|Tail]) ->
+ F(Hd),
+ foreach_3(F, Tail);
+foreach_3(F, []) -> ok.
+
+mapfoldl_3(F, Accu0, [Hd|Tail]) ->
+ {R,Accu1} = F(Hd, Accu0),
+ {Rs,Accu2} = mapfoldl_3(F, Accu1, Tail),
+ {[R|Rs],Accu2};
+mapfoldl_3(F, Accu, []) -> {[],Accu}.
+
+mapfoldr_3(F, Accu0, [Hd|Tail]) ->
+ {Rs,Accu1} = mapfoldr_3(F, Accu0, Tail),
+ {R,Accu2} = F(Hd, Accu1),
+ {[R|Rs],Accu2};
+mapfoldr_3(F, Accu, []) -> {[],Accu}.
+
+takewhile_3(Pred, [Hd|Tail]) ->
+ case Pred(Hd) of
+ true -> [Hd|takewhile_3(Pred, Tail)];
+ false -> []
+ end;
+takewhile_3(Pred, []) -> [].
+
+dropwhile_3(Pred, [Hd|Tail]) ->
+ case Pred(Hd) of
+ true -> dropwhile_3(Pred, Tail);
+ false -> [Hd|Tail]
+ end;
+dropwhile_3(Pred, []) -> [].
+
+splitwith_3(Pred, List) -> splitwith_3(Pred, List, []).
+
+splitwith_3(Pred, [Hd|Tail], Taken) ->
+ case Pred(Hd) of
+ true -> splitwith_3(Pred, Tail, [Hd|Taken]);
+ false -> {reverse_3(Taken), [Hd|Tail]}
+ end;
+splitwith_3(Pred, [], Taken) -> {reverse_3(Taken),[]}.
+
+%% Versions of the above functions with extra arguments.
+
+all_3(Pred, Eas, [Hd|Tail]) ->
+ case apply(Pred, [Hd|Eas]) of
+ true -> all_3(Pred, Eas, Tail);
+ false -> false
+ end;
+all_3(Pred, Eas, []) -> true.
+
+any_3(Pred, Eas, [Hd|Tail]) ->
+ case apply(Pred, [Hd|Eas]) of
+ true -> true;
+ false -> any_3(Pred, Eas, Tail)
+ end;
+any_3(Pred, Eas, []) -> false.
+
+map_3(F, Eas, List) -> [ apply(F, [E|Eas]) || E <- List ].
+
+flatmap_3(F, Eas, [Hd|Tail]) ->
+ apply(F, [Hd|Eas]) ++ flatmap_3(F, Eas, Tail);
+flatmap_3(F, Eas, []) -> [].
+
+foldl_3(F, Eas, Accu, [Hd|Tail]) ->
+ foldl_3(F, Eas, apply(F, [Hd,Accu|Eas]), Tail);
+foldl_3(F, Eas, Accu, []) -> Accu.
+
+foldr_3(F, Eas, Accu, [Hd|Tail]) ->
+ apply(F, [Hd,foldr_3(F, Eas, Accu, Tail)|Eas]);
+foldr_3(F, Eas, Accu, []) ->
+ Accu.
+
+filter_3(Pred, Eas, List) -> [ E || E <- List, apply(Pred, [E|Eas]) ].
+
+zF_3(F, Eas, [Hd|Tail]) ->
+ case apply(F, [Hd|Eas]) of
+ true ->
+ [Hd|zF(F, Eas, Tail)];
+ {true,Val} ->
+ [Val|zF(F, Eas, Tail)];
+ false ->
+ zF(F, Eas, Tail)
+ end;
+zF_3(F, Eas, []) -> [].
+
+foreach_3(F, Eas, [Hd|Tail]) ->
+ apply(F, [Hd|Eas]),
+ foreach_3(F, Eas, Tail);
+foreach_3(F, Eas, []) -> ok.
+
+mapfoldl_3(F, Eas, Accu0, [Hd|Tail]) ->
+ {R,Accu1} = apply(F, [Hd,Accu0|Eas]),
+ {Rs,Accu2} = mapfoldl_3(F, Eas, Accu1, Tail),
+ {[R|Rs],Accu2};
+mapfoldl_3(F, Eas, Accu, []) -> {[],Accu}.
+
+mapfoldr_3(F, Eas, Accu0, [Hd|Tail]) ->
+ {Rs,Accu1} = mapfoldr_3(F, Eas, Accu0, Tail),
+ {R,Accu2} = apply(F, [Hd,Accu1|Eas]),
+ {[R|Rs],Accu2};
+mapfoldr_3(F, Eas, Accu, []) -> {[],Accu}.
+
+%% takewhile/2, dropwhile/2 and splitwith/2 do not have versions with
+%% extra arguments as this going to be discontinued.
+
+
+
+
+lots_of_atoms () ->
+
+Aa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Af = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ag = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ah = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aba = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aca = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ada = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aea = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aga = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aha = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aec = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Add = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aed = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ace = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ade = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aee = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Age = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+
+
+Aaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aabaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aebaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aacaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Accaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aecaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aadaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Addaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aedaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aceaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ageaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aheaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+
+Aaaaaa= 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aabaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aebaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aacaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Accaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aecaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aadaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Addaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aedaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aceaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ageaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aheaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg'.
+
+
+lots_of_atoms1 () ->
+
+Aa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Af = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ag = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ah = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aba = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aca = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ada = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aea = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aga = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aha = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aec = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Add = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aed = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ace = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ade = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aee = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Age = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+
+
+Aaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aabaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aebaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aacaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Accaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aecaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aadaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Addaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aedaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aceaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ageaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aheaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+
+Aaaaaa= 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aabaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aebaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aacaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Accaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aecaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aadaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Addaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aedaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aceaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ageaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aheaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg'.
+
+
+lots_of_atoms2 () ->
+
+Aa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Af = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ag = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ah = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aba = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aca = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ada = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aea = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aga = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aha = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aec = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Add = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aed = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ace = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ade = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aee = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Age = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+
+
+Aaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aabaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aebaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aacaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Accaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aecaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aadaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Addaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aedaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aceaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ageaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aheaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+
+Aaaaaa= 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aabaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aebaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aacaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Accaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aecaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aadaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Addaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aedaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aceaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ageaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aheaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg'.
+
+
+lots_of_atoms3 () ->
+
+Aa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Af = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ag = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ah = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aba = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aca = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ada = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aea = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aga = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aha = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aec = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Add = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aed = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ace = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ade = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aee = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Age = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+
+
+Aaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aabaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aebaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aacaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Accaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aecaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aadaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Addaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aedaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aceaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ageaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aheaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+
+Aaaaaa= 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aabaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aebaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aacaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Accaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aecaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aadaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Addaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aedaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aceaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ageaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aheaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg'.
+
+
+lots_of_atoms4 () ->
+
+Aa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Af = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ag = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ah = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aba = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aca = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ada = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aea = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aga = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aha = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aec = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Add = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aed = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ace = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ade = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aee = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Age = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+
+
+Aaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aabaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aebaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aacaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Accaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aecaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aadaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Addaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aedaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aceaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ageaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aheaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+
+Aaaaaa= 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aabaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aebaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aacaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Accaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aecaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aadaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Addaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aedaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aceaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ageaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aheaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg'.
+
+
+lots_of_atoms5 () ->
+
+Aa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Af = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ag = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ah = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aba = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aca = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ada = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aea = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aga = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aha = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aec = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Add = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aed = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ace = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ade = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aee = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Age = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+
+
+Aaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aabaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aebaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aacaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Accaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aecaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aadaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Addaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aedaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aceaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ageaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aheaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+
+Aaaaaa= 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aabaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aebaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aacaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Accaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aecaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aadaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Addaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aedaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aceaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ageaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aheaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg'.
+
+
+lots_of_atoms6 () ->
+
+Aa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Af = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ag = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ah = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aba = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aca = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ada = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aea = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aga = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aha = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aec = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Add = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aed = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ace = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ade = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aee = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Age = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+
+
+Aaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aabaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aebaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aacaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Accaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aecaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aadaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Addaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aedaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aceaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ageaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aheaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+
+Aaaaaa= 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aabaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aebaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aacaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Accaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aecaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aadaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Addaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aedaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aceaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ageaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aheaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg'.
+
+
+lots_of_atoms7 () ->
+
+Aa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Af = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ag = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ah = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aba = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aca = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ada = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aea = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aga = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aha = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aec = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Add = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aed = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ace = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ade = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aee = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Age = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+
+
+Aaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aabaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aebaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aacaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Accaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aecaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aadaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Addaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aedaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aceaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ageaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aheaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+
+Aaaaaa= 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aabaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aebaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aacaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Accaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aecaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aadaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Addaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aedaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aceaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ageaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aheaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg'.
+
+
+lots_of_atoms8 () ->
+
+Aa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Af = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ag = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ah = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aba = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aca = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ada = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aea = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aga = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aha = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aec = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Add = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aed = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ace = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ade = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aee = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Age = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+
+
+Aaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aabaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aebaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aacaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Accaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aecaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aadaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Addaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aedaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aceaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ageaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aheaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+
+Aaaaaa= 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aabaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aebaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aacaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Accaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aecaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aadaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Addaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aedaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aceaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ageaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aheaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg'.
+
+
+lots_of_atoms9 () ->
+
+Aa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Af = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ag = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ah = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aba = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aca = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ada = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aea = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aga = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aha = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aec = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Add = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aed = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ace = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ade = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aee = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Age = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+
+
+Aaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aabaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aebaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aacaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Accaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aecaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aadaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Addaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aedaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aceaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ageaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aheaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+
+Aaaaaa= 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aabaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aebaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aacaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Accaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aecaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aadaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Addaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aedaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aceaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ageaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aheaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg'.
+
+
+lots_of_atoms10 () ->
+
+Aa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Af = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ag = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ah = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aba = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aca = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ada = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aea = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aga = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aha = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aec = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Add = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aed = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ace = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ade = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aee = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Age = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+
+
+Aaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aabaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aebaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aacaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Accaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aecaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aadaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Addaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aedaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aceaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ageaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aheaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+
+Aaaaaa= 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aabaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aebaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aacaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Accaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aecaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aadaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Addaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aedaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aceaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ageaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aheaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg'.
+
+
+lots_of_atoms11 () ->
+
+Aa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Af = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ag = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ah = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aba = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aca = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ada = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aea = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aga = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aha = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aec = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Add = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aed = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ace = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ade = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aee = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Age = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+
+
+Aaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aabaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aebaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aacaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Accaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aecaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aadaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Addaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aedaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aceaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ageaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aheaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+
+Aaaaaa= 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aabaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aebaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aacaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Accaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aecaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aadaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Addaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aedaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aceaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ageaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aheaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg'.
+
+
+lots_of_atoms12 () ->
+
+Aa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Af = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ag = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ah = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aba = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aca = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ada = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aea = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aga = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aha = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aab = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahb = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aac = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aec = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahc = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aad = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Add = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aed = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahd = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aae = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ace = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ade = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aee = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Age = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahe = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+
+
+Aaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aabaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aebaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahbaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aacaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Accaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aecaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahcaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aadaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Addaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aedaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahdaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aceaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afeaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ageaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aheaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+
+Aaaaaa= 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahaaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aabaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aebaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahbaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aacaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Accaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aecaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahcaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aadaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Acdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Addaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aedaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Agdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ahdaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aaeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Abeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aceaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Adeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aeeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Afeaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Ageaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg',
+
+Aheaaa = 'rnevgoirnvire iriej iirejgierjg ioegjrigj oiegj oijetig oijtgej oj oiejg iojetijwokfopkewmf irjgo ergjerifjiugnuignuit euhg uieuignuiergnuienrgueringiun uiegniuerngui iugne uegniuetgniuetgnuientg unegngiuethgiueugnieg'.
diff --git a/lib/debugger/test/int_SUITE_data/ordsets1.erl b/lib/debugger/test/int_SUITE_data/ordsets1.erl
new file mode 100644
index 0000000000..a01d35eb51
--- /dev/null
+++ b/lib/debugger/test/int_SUITE_data/ordsets1.erl
@@ -0,0 +1,191 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Copyright (C) 1991, Ellemtel Telecommunications Systems Laboratories
+%% File : ordsets.erl
+%% Author : Robert Virding
+%% Purpose : Functions for manipulating sets as ordered lists.
+
+%% As yet some of these are not very efficiently written.
+
+-module(ordsets1).
+
+-export([new_set/0,is_set/1,set_to_list/1,list_to_set/1]).
+-export([is_element/2,add_element/2,del_element/2]).
+-export([union/2,union/1,intersection/2,intersection/1]).
+-export([subtract/2,subset/2]).
+
+%% new_set()
+%% Return a new empty ordered set.
+
+new_set() ->
+ [].
+
+%% is_set(Set)
+%% Return 'true' if Set is an ordered set of elements, else 'false'.
+
+is_set([E|Es]) ->
+ is_set(Es, E);
+is_set([]) ->
+ true.
+
+is_set([E2|Es], E1) when E1 < E2 ->
+ is_set(Es, E2);
+is_set([E2|Es], E1) ->
+ false;
+is_set([], E1) ->
+ true.
+
+%% set_to_list(OrdSet)
+%% Return the elements in OrdSet as a list.
+
+set_to_list(S) ->
+ S.
+
+%% list_to_set(List)
+%% Build an ordered set from the elements in List.
+
+list_to_set([E|Es]) ->
+ add_element(E, list_to_set(Es));
+list_to_set([]) ->
+ [].
+
+%% is_element(Element, OrdSet)
+%% Return 'true' if Element is an element of OrdSet, else 'false'.
+
+is_element(E, [H|Es]) when E < H ->
+ false;
+is_element(E, [H|Es]) when E == H ->
+ true;
+is_element(E, [H|Es]) when E > H ->
+ is_element(E, Es);
+is_element(E, []) ->
+ false.
+
+%% add_element(Element, OrdSet)
+%% Return OrdSet with Element inserted in it.
+
+add_element(E, [H|Es]) when E < H ->
+ [E,H|Es];
+add_element(E, [H|Es]) when E == H ->
+ [H|Es];
+add_element(E, [H|Es]) when E > H ->
+ [H|add_element(E, Es)];
+add_element(E, []) ->
+ [E].
+
+%% del_element(Element, OrdSet)
+%% Return OrdSet but with Element removed.
+
+del_element(E, [H|Es]) when E < H ->
+ [H|Es];
+del_element(E, [H|Es]) when E == H ->
+ Es;
+del_element(E, [H|Es]) when E > H ->
+ [H|del_element(E, Es)];
+del_element(E, []) ->
+ [].
+
+%% union(Set1, Set2)
+%% Return the union of Set1 and Set2.
+
+union([H1|Es1], [H2|Es2]) when H1 < H2 ->
+ [H1|union(Es1, [H2|Es2])];
+union([H1|Es1], [H2|Es2]) when H1 == H2 ->
+ [H1|union(Es1, Es2)];
+union([H1|Es1], [H2|Es2]) when H1 > H2 ->
+ [H2|union([H1|Es1], Es2)];
+union([], Es2) ->
+ Es2;
+union(Es1, []) ->
+ Es1.
+
+%% union(OrdSets)
+%% Return the union of the list of sets.
+
+union([S1,S2|Ss]) ->
+ union1(union(S1,S2), Ss);
+union([S]) ->
+ S;
+union([]) ->
+ [].
+
+union1(S1, [S2|Ss]) ->
+ union1(union(S1, S2), Ss);
+union1(S1, []) ->
+ S1.
+
+%% intersection(Set1, Set2)
+%% Return the intersection of Set1 and Set2.
+
+intersection([H1|Es1], [H2|Es2]) when H1 < H2 ->
+ intersection(Es1, [H2|Es2]);
+intersection([H1|Es1], [H2|Es2]) when H1 == H2 ->
+ [H1|intersection(Es1, Es2)];
+intersection([H1|Es1], [H2|Es2]) when H1 > H2 ->
+ intersection([H1|Es1], Es2);
+intersection([], Es2) ->
+ [];
+intersection(Es1, []) ->
+ [].
+
+%% intersection(OrdSets)
+%% Return the intersection of the list of sets.
+
+intersection([S1,S2|Ss]) ->
+ intersection1(intersection(S1,S2), Ss);
+intersection([S]) ->
+ S;
+intersection([]) ->
+ [].
+
+intersection1(S1, [S2|Ss]) ->
+ intersection1(intersection(S1, S2), Ss);
+intersection1(S1, []) ->
+ S1.
+
+%% subtract(Set1, Set2)
+%% Return all and only the elements of Set1 which are not also in Set2.
+
+subtract([H1|Es1], [H2|Es2]) when H1 < H2 ->
+ [H1|subtract(Es1, [H2|Es2])];
+subtract([H1|Es1], [H2|Es2]) when H1 == H2 ->
+ subtract(Es1, Es2);
+subtract([H1|Es1], [H2|Es2]) when H1 > H2 ->
+ subtract([H1|Es1], Es2);
+subtract([], Es2) ->
+ [];
+subtract(Es1, []) ->
+ Es1.
+
+%% subset(Set1, Set2)
+%% Return 'true' when every element of Set1 is also a member of Set2,
+%% else 'false'.
+
+subset([H1|Es1], [H2|Es2]) when H1 < H2 -> %H1 not in Set2
+ false;
+subset([H1|Es1], [H2|Es2]) when H1 == H2 ->
+ subset(Es1, Es2);
+subset([H1|Es1], [H2|Es2]) when H1 > H2 ->
+ subset([H1|Es1], Es2);
+subset([], Es2) ->
+ true;
+subset(Es1, []) ->
+ false.
diff --git a/lib/debugger/test/int_SUITE_data/test.erl b/lib/debugger/test/int_SUITE_data/test.erl
new file mode 100644
index 0000000000..679b266380
--- /dev/null
+++ b/lib/debugger/test/int_SUITE_data/test.erl
@@ -0,0 +1,152 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(test).
+
+%%-compile(export_all).
+-export([test1/0,
+ test2/0,
+ test3/0,
+ test4/0,
+ test5/0,
+ test6/1,
+ test7/0,
+ test8/1,
+ test9/0,
+ test10/0,
+ test11/0
+ ]).
+
+
+-export([test9_server/1]).
+
+
+test1() ->
+ R1 = lists1:reverse("retep"),
+ R2 = ordsets1:list_to_set([b,c,a,2,4,1]),
+ R3 = lists1:reverse("nilo"),
+ {R1,R2, R3}.
+
+test2() ->
+ R1 = spawn(lists1,reverse,["retep"]),
+ R2 = spawn(ordsets1,list_to_set,[[b,c,a,2,4,1]]),
+ R3 = spawn(lists1,reverse,["nilo"]),
+ {R1,R2, R3}.
+
+
+test3() ->
+ A = a,
+ Pid = spawn(?MODULE, test1,[]),
+ B = b,
+ {A, B, Pid}.
+
+test4() ->
+ Pid = spawn(?MODULE, test1,[]),
+ A = a,
+ B = b,
+ {A, B, Pid}.
+test5() ->
+ L1 = [a,b,c],
+ L = length(L1),
+ A = a,
+ B = b,
+ {A, B, L, L1}.
+
+
+
+test6(0) ->
+ ok;
+test6(N) when N>0 ->
+ spawn(lists1,reverse,["adolfiparisrorsirapifloda"]),
+ test6(N-1).
+
+
+test7() ->
+ CurDirReturn = file:get_cwd(),
+ {ok, CurDir} = CurDirReturn,
+ DirListReturn = file:list_dir(CurDir),
+ {ok, DirList} = DirListReturn,
+ io:format("~w~n",[DirList]).
+
+
+test8(List) ->
+ %% foo
+ %%bar
+ %% foo
+ %%bar
+ %% foo
+ %%bar
+ %% foo
+ %%bar
+
+ L2 = [gamma|List],
+ {L2, List}.
+
+test9() ->
+ S1 = spawn(?MODULE, test9_server,[self()]),
+ S2 = spawn(?MODULE, test9_server,[bongo]),
+ S3 = spawn(?MODULE, test9_server,[42]),
+
+ test9_loop(S1,S2,S3).
+
+test9_loop(S1,S2,S3) ->
+ receive
+ {S1, hej} ->
+ io:format("S1 ~n"),
+ test9_loop(S1,S2,S3);
+ {S2, hej} ->
+ io:format("S2 ~n"),
+ test9_loop(S1,S2,S3);
+ {S3, hej} ->
+ io:format("S3 ~n"),
+ test9_loop(S1,S2,S3)
+ end.
+
+
+test9_server(Pid) ->
+ io:format("started server: ~p~n",[Pid]),
+ test9_server1(Pid).
+
+test9_server1(Pid) ->
+ Pad = {pad, Pid},
+ test9_server2(Pad).
+
+test9_server2(Pad) ->
+ {pad, Pid} = Pad,
+ Pid ! {self(), hej}.
+
+
+
+
+
+test10() ->
+ receive
+ X ->
+ done
+ after 20000 ->
+ timeout
+ end.
+
+test11() ->
+ receive
+ X ->
+ done
+ end.
diff --git a/lib/debugger/test/int_SUITE_data/test1.erl b/lib/debugger/test/int_SUITE_data/test1.erl
new file mode 100644
index 0000000000..a93416cbac
--- /dev/null
+++ b/lib/debugger/test/int_SUITE_data/test1.erl
@@ -0,0 +1,34 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-module(test1).
+
+-compile(export_all).
+
+
+foo() ->
+ A = [1,2,3],
+ B = [a,b,c],
+ C = [d,e,f],
+ D = my_lists:append(A,B),
+ E = my_lists:append(D,C),
+ F = [1],
+ G = my_lists:append(E,F),
+ {A,B,C,D,E,F,G}.
diff --git a/lib/debugger/test/int_break_SUITE.erl b/lib/debugger/test/int_break_SUITE.erl
new file mode 100644
index 0000000000..b7b3c5598a
--- /dev/null
+++ b/lib/debugger/test/int_break_SUITE.erl
@@ -0,0 +1,92 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-module(int_break_SUITE).
+
+%% Test break points.
+
+-include("test_server.hrl").
+
+-export([all/1,init_per_testcase/2,fin_per_testcase/2,
+ basic/1,cleanup/1]).
+
+-export([auto_attach/1]).
+
+all(suite) ->
+ [basic,cleanup].
+
+init_per_testcase(_Case, Config) ->
+ ?line DataDir = ?config(data_dir, Config),
+ ?line Mod = ordsets1,
+ ?line {module,Mod} = int:i(filename:join(DataDir, Mod)),
+ ?line ok = io:format("Interpreted modules: ~p", [int:interpreted()]),
+ ?line Dog = test_server:timetrap(?t:minutes(0.5)),
+ [{watchdog,Dog}|Config].
+
+fin_per_testcase(_Case, Config) ->
+ ?line ok = io:format("Interpreted modules: ~p", [int:interpreted()]),
+ ?line Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+basic(doc) -> "Tests setting a few break points.";
+basic(suite) -> [];
+basic(Config) when list(Config) ->
+ ?line int:auto_attach([init], {?MODULE,auto_attach}),
+ ?line S1 = [] = ordsets1:new_set(),
+ ?line ok = i:ib(ordsets1, 86),
+ ?line S2 = [xxx] = ordsets1:add_element(xxx, S1),
+ ?line S3 = [xxx,y] = ordsets1:add_element(y, S2),
+ ?line ok = i:ib(ordsets1, union, 2),
+ ?line [xxx,y,z] = ordsets1:union(S3, [z]),
+ ok.
+
+cleanup(doc) -> "Make sure that the auto-attach flag is turned off.";
+cleanup(suite) -> [];
+cleanup(Config) when list(Config) ->
+ ?line int:auto_attach(false),
+ ok.
+
+auto_attach(Pid) ->
+ {ok, Meta} = int:attached(Pid),
+ io:format("Pid = ~p; Meta = ~p", [Pid,Meta]),
+ link(Meta),
+ attach_loop(Pid, Meta).
+
+attach_loop(Pid, Meta) ->
+ receive
+ Msg ->
+ io:format("attached: ~p", [Msg]),
+ attach_cmd(Msg, Pid, Meta),
+ attach_loop(Pid, Meta)
+ end.
+
+attach_cmd({Meta,{break_at,ordsets1,36,2}}, _Pid, Meta) ->
+ int:meta(Meta, continue);
+attach_cmd({Meta,{break_at,ordsets1,87,_}}, _Pid, Meta) ->
+ int:meta(Meta, continue);
+attach_cmd({Meta,{break_at,ordsets1,89,_}}, _Pid, Meta) ->
+ int:meta(Meta, continue);
+attach_cmd({Meta,{break_at,ordsets1,Line,_}}, _Pid, Meta) when 107 =< Line, Line =< 115 ->
+ int:meta(Meta, finish);
+attach_cmd({Meta,{break_at,_Mod,_Line,_Other}}=Cmd, _Pid, Meta) ->
+ io:format("attached: no action for ~p", [Cmd]);
+attach_cmd(_, _Pid, _Meta) ->
+ ok.
diff --git a/lib/debugger/test/int_break_SUITE_data/Makefile.src b/lib/debugger/test/int_break_SUITE_data/Makefile.src
new file mode 100644
index 0000000000..0d1ee35a67
--- /dev/null
+++ b/lib/debugger/test/int_break_SUITE_data/Makefile.src
@@ -0,0 +1,25 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2000-2010. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+
+EFLAGS=+debug_info
+
+all: ordsets1.@EMULATOR@
+
+ordsets1.@EMULATOR@: ordsets1.erl
+ erlc $(EFLAGS) ordsets1.erl
diff --git a/lib/debugger/test/int_break_SUITE_data/ordsets1.erl b/lib/debugger/test/int_break_SUITE_data/ordsets1.erl
new file mode 100644
index 0000000000..6300c6097c
--- /dev/null
+++ b/lib/debugger/test/int_break_SUITE_data/ordsets1.erl
@@ -0,0 +1,188 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Purpose : Functions for manipulating sets as ordered lists.
+
+%% As yet some of these are not very efficiently written.
+
+-module(ordsets1).
+
+-export([new_set/0,is_set/1,set_to_list/1,list_to_set/1]).
+-export([is_element/2,add_element/2,del_element/2]).
+-export([union/2,union/1,intersection/2,intersection/1]).
+-export([subtract/2,subset/2]).
+
+%% new_set()
+%% Return a new empty ordered set.
+
+new_set() ->
+ [].
+
+%% is_set(Set)
+%% Return 'true' if Set is an ordered set of elements, else 'false'.
+
+is_set([E|Es]) ->
+ is_set(Es, E);
+is_set([]) ->
+ true.
+
+is_set([E2|Es], E1) when E1 < E2 ->
+ is_set(Es, E2);
+is_set([E2|Es], E1) ->
+ false;
+is_set([], E1) ->
+ true.
+
+%% set_to_list(OrdSet)
+%% Return the elements in OrdSet as a list.
+
+set_to_list(S) ->
+ S.
+
+%% list_to_set(List)
+%% Build an ordered set from the elements in List.
+
+list_to_set([E|Es]) ->
+ add_element(E, list_to_set(Es));
+list_to_set([]) ->
+ [].
+
+%% is_element(Element, OrdSet)
+%% Return 'true' if Element is an element of OrdSet, else 'false'.
+
+is_element(E, [H|Es]) when E < H ->
+ false;
+is_element(E, [H|Es]) when E == H ->
+ true;
+is_element(E, [H|Es]) when E > H ->
+ is_element(E, Es);
+is_element(E, []) ->
+ false.
+
+%% add_element(Element, OrdSet)
+%% Return OrdSet with Element inserted in it.
+
+add_element(E, [H|_]=Es) when E < H ->
+ [E|Es];
+add_element(E, [H|_]=Es) when E == H ->
+ Es;
+add_element(E, [H|Es]) when E > H ->
+ [H|add_element(E, Es)];
+add_element(E, []) ->
+ [E].
+
+%% del_element(Element, OrdSet)
+%% Return OrdSet but with Element removed.
+
+del_element(E, [H|_]=Es) when E < H ->
+ Es;
+del_element(E, [H|Es]) when E == H ->
+ Es;
+del_element(E, [H|Es]) when E > H ->
+ [H|del_element(E, Es)];
+del_element(E, []) ->
+ [].
+
+%% union(Set1, Set2)
+%% Return the union of Set1 and Set2.
+
+union([H1|Es1], [H2|_]=Es2) when H1 < H2 ->
+ [H1|union(Es1, Es2)];
+union([H1|Es1], [H2|Es2]) when H1 == H2 ->
+ [H1|union(Es1, Es2)];
+union([H1|_]=Es1, [H2|Es2]) when H1 > H2 ->
+ [H2|union(Es1, Es2)];
+union([], Es2) ->
+ Es2;
+union(Es1, []) ->
+ Es1.
+
+%% union(OrdSets)
+%% Return the union of the list of sets.
+
+union([S1,S2|Ss]) ->
+ union1(union(S1,S2), Ss);
+union([S]) ->
+ S;
+union([]) ->
+ [].
+
+union1(S1, [S2|Ss]) ->
+ union1(union(S1, S2), Ss);
+union1(S1, []) ->
+ S1.
+
+%% intersection(Set1, Set2)
+%% Return the intersection of Set1 and Set2.
+
+intersection([H1|Es1], [H2|_]=Es2) when H1 < H2 ->
+ intersection(Es1, Es2);
+intersection([H1|Es1], [H2|Es2]) when H1 == H2 ->
+ [H1|intersection(Es1, Es2)];
+intersection([H1|_]=Es1, [H2|Es2]) when H1 > H2 ->
+ intersection(Es1, Es2);
+intersection([], Es2) ->
+ [];
+intersection(Es1, []) ->
+ [].
+
+%% intersection(OrdSets)
+%% Return the intersection of the list of sets.
+
+intersection([S1,S2|Ss]) ->
+ intersection1(intersection(S1,S2), Ss);
+intersection([S]) ->
+ S;
+intersection([]) ->
+ [].
+
+intersection1(S1, [S2|Ss]) ->
+ intersection1(intersection(S1, S2), Ss);
+intersection1(S1, []) ->
+ S1.
+
+%% subtract(Set1, Set2)
+%% Return all and only the elements of Set1 which are not also in Set2.
+
+subtract([H1|Es1], [H2|_]=Es2) when H1 < H2 ->
+ [H1|subtract(Es1, Es2)];
+subtract([H1|Es1], [H2|Es2]) when H1 == H2 ->
+ subtract(Es1, Es2);
+subtract([H1|_]=Es1, [H2|Es2]) when H1 > H2 ->
+ subtract(Es1, Es2);
+subtract([], Es2) ->
+ [];
+subtract(Es1, []) ->
+ Es1.
+
+%% subset(Set1, Set2)
+%% Return 'true' when every element of Set1 is also a member of Set2,
+%% else 'false'.
+
+subset([H1|Es1], [H2|Es2]) when H1 < H2 -> %H1 not in Set2
+ false;
+subset([H1|Es1], [H2|Es2]) when H1 == H2 ->
+ subset(Es1, Es2);
+subset([H1|Es1], [H2|Es2]) when H1 > H2 ->
+ subset([H1|Es1], Es2);
+subset([], Es2) ->
+ true;
+subset(Es1, []) ->
+ false.
diff --git a/lib/debugger/test/int_eval_SUITE.erl b/lib/debugger/test/int_eval_SUITE.erl
new file mode 100644
index 0000000000..19b006e750
--- /dev/null
+++ b/lib/debugger/test/int_eval_SUITE.erl
@@ -0,0 +1,277 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-module(int_eval_SUITE).
+
+%% Purpose: Deeper test of the evaluator.
+
+-export([all/1,init_per_testcase/2, fin_per_testcase/2,
+ bifs_outside_erlang/1, spawning/1, applying/1,
+ catch_and_throw/1, external_call/1, test_module_info/1,
+ apply_interpreted_fun/1, apply_uninterpreted_fun/1,
+ interpreted_exit/1, otp_8310/1]).
+
+%% Helpers.
+-export([applier/3]).
+
+-define(IM, my_int_eval_module).
+
+-include("test_server.hrl").
+
+all(suite) ->
+ [bifs_outside_erlang,spawning,applying,catch_and_throw,
+ external_call,test_module_info,
+ apply_interpreted_fun,apply_uninterpreted_fun,
+ interpreted_exit, otp_8310].
+
+init_per_testcase(_Case, Config) ->
+ ?line DataDir = ?config(data_dir, Config),
+ ?line {module,?IM} = int:i(filename:join(DataDir, ?IM)),
+ ?line ok = io:format("Interpreted modules: ~p",[int:interpreted()]),
+ {ok, Dog} = timer:apply_after(timer:minutes(1),
+ erlang, exit, [self(), kill]),
+ [{watchdog,Dog}|Config].
+
+fin_per_testcase(_Case, Config) ->
+ ok = io:format("Interpreted modules: ~p", [int:interpreted()]),
+ Dog = ?config(watchdog, Config),
+ timer:cancel(Dog),
+ ok.
+
+bifs_outside_erlang(doc) ->
+ "Test that BIFs outside the erlang module are correctly evaluated.";
+bifs_outside_erlang(suite) ->
+ [];
+bifs_outside_erlang(Config) when is_list(Config) ->
+ Fun = fun() ->
+ Id = ?IM:ets_new(),
+ Self = self(),
+ ok = io:format("Self: ~p", [Self]),
+ Info = ets:info(Id),
+ {owner,Self} = lists:nth(2, Info),
+ %% Was
+ %% {owner,Self} = element(2, Info),
+ %% in R10B.
+ ?IM:ets_delete(Id),
+ ok
+ end,
+ ?line ok = spawn_eval(Fun),
+ ok.
+
+spawning(doc) ->
+ "Try evalutate spawn_link/3.";
+spawning(suite) ->
+ [];
+spawning(Config) when is_list(Config) ->
+ ?line ok = spawn_eval(fun() -> ?IM:spawn_test() end).
+
+applying(doc) ->
+ "Try various sorts of applies.";
+applying(suite) ->
+ [];
+applying(Config) when is_list(Config) ->
+ Fun = fun({number,X}, {number,Y}) -> X+Y end,
+ ?line ok = spawn_eval(fun() -> ?IM:apply_test(Fun) end).
+
+catch_and_throw(doc) ->
+ "Test catch and throw/1.";
+catch_and_throw(suite) ->
+ [];
+catch_and_throw(Config) when is_list(Config) ->
+ {a,ball} = spawn_eval(fun() -> ok = ?IM:catch_a_ball(),
+ catch ?IM:throw_a_ball() end),
+
+ %% Throw and catch without any extra outer catch.
+
+ ?line process_flag(trap_exit, true),
+ ?line Pid1 = spawn_link(fun() -> exit(?IM:catch_a_ball()) end),
+ receive
+ {'EXIT',Pid1,ok} -> ok;
+ {'EXIT',Pid1,Bad1} -> ?line ?t:fail({bad_message,Bad1})
+ after 5000 ->
+ ?line ?t:fail(timeout)
+ end,
+
+
+ %% Throw without catch.
+
+ ?line Pid2 = spawn_link(fun() -> ?IM:throw_a_ball() end),
+ receive
+ {'EXIT',Pid2,{{nocatch,{a,ball}},[_|_]}} -> ok;
+ {'EXIT',Pid2,Bad2} -> ?line ?t:fail({bad_message,Bad2})
+ after 5000 ->
+ ?line ?t:fail(timeout)
+ end,
+
+ ?line ok = ?IM:more_catch(fun(_) -> ?IM:exit_me() end),
+ ?line ok = ?IM:more_catch(fun(_) -> exit({unint, exit}) end),
+ ?line {a, ball} = ?IM:more_catch(fun(_) -> ?IM:throw_a_ball() end),
+ ?line {b, ball} = ?IM:more_catch(fun(_) -> throw({b,ball}) end),
+
+ ExitInt = {'EXIT',{int,exit}},
+ ExitU = {'EXIT',{unint,exit}},
+
+ ?line ExitInt = (catch ?IM:more_nocatch(fun(_) -> ?IM:exit_me() end)),
+ ?line ExitU = (catch ?IM:more_nocatch(fun(_) -> exit({unint, exit}) end)),
+ ?line {a, ball} = (catch {error, ?IM:more_nocatch(fun(_) -> ?IM:throw_a_ball() end)}),
+ ?line {b, ball} = (catch {error, ?IM:more_nocatch(fun(_) -> throw({b,ball}) end)}),
+ ok.
+
+external_call(doc) ->
+ "Test external calls.";
+external_call(suite) ->
+ [];
+external_call(Config) when is_list(Config) ->
+ ?line ok = spawn_eval(fun() -> ?IM:external_call_test({some,stupid,data}) end).
+
+test_module_info(doc) ->
+ "Test the module_info/0,1 functions.";
+test_module_info(suite) ->
+ [];
+test_module_info(Config) when is_list(Config) ->
+ ?line ModInfo = ?IM:module_info(),
+ ?line {value,{exports,Exp}} = lists:keysearch(exports, 1, ModInfo),
+ ?line {value,{attributes,Attr}} = lists:keysearch(attributes, 1, ModInfo),
+ ?line Exp = ?IM:module_info(exports),
+ ?line Attr = ?IM:module_info(attributes),
+ ?line {value,{stupid_attribute,[{a,b}]}} =
+ lists:keysearch(stupid_attribute, 1, Attr),
+
+ %% Check exports using a list comprehension in the module itself.
+
+ ?line ok = ?IM:check_exports(Exp),
+
+ %% Call module_info/0,1 from the module itself.
+
+ ?line ok = ?IM:check_module_info(ModInfo, Exp),
+
+ ok.
+
+apply_interpreted_fun(doc) ->
+ "Apply a fun defined in interpreted code.";
+apply_interpreted_fun(suite) -> [];
+apply_interpreted_fun(Config) when is_list(Config) ->
+
+ %% Called from uninterpreted code
+ ?line F1 = spawn_eval(fun() -> ?IM:give_me_a_fun_0() end),
+ ?line perfectly_alright = spawn_eval(fun() -> F1() end),
+ ?line ATerm = {a,term},
+ ?line F2 = spawn_eval(fun() -> ?IM:give_me_a_fun_0(ATerm) end),
+ ?line {ok,ATerm} = spawn_eval(fun() -> F2() end),
+
+ %% Called from uninterpreted code, badarity
+ ?line {'EXIT',{{badarity,{F1,[snape]}},[{?MODULE,_,_}|_]}} =
+ spawn_eval(fun() -> F1(snape) end),
+
+ %% Called from uninterpreted code, error in fun
+ ?line F3 = spawn_eval(fun() -> ?IM:give_me_a_bad_fun() end),
+ ?line {'EXIT',{snape,[{?IM,_FunName,_}|_]}} =
+ spawn_eval(fun() -> F3(snape) end),
+
+ %% Called from within interpreted code
+ ?line perfectly_alright = spawn_eval(fun() -> ?IM:do_apply(F1) end),
+
+ %% Called from within interpreted code, badarity
+ ?line {'EXIT',{{badarity,{F1,[snape]}},[{?IM,do_apply,_}|_]}} =
+ spawn_eval(fun() -> ?IM:do_apply(F1, snape) end),
+
+ %% Called from within interpreted code, error in fun
+ ?line {'EXIT',{snape,[{?IM,_FunName,_}|_]}} =
+ spawn_eval(fun() -> ?IM:do_apply(F3, snape) end),
+
+ %% Try some more complex funs.
+ ?line F4 = ?IM:give_me_a_fun_1(14, 42),
+ ?line {false,yes,yeah,false} =
+ F4({{1,nope},{14,yes},{42,yeah},{100,forget_it}}),
+ ?line [this_is_ok,me_too] =
+ F4([{-24,no_way},{15,this_is_ok},{1333,forget_me},{37,me_too}]),
+
+ %% OTP-5837
+ %% Try fun with guard containing variable bound in environment
+ ?line [yes,no,no,no] = ?IM:otp_5837(1),
+
+ ok.
+
+apply_uninterpreted_fun(doc) ->
+ "Apply a fun defined outside interpreted code.";
+apply_uninterpreted_fun(suite) -> [];
+apply_uninterpreted_fun(Config) when is_list(Config) ->
+
+ ?line F1 = fun(snape) ->
+ erlang:error(snape);
+ (_Arg) ->
+ perfectly_alright
+ end,
+
+ %% Ok
+ ?line perfectly_alright =
+ spawn_eval(fun() -> ?IM:do_apply(F1, any_arg) end),
+
+ %% Badarity (evaluated in dbg_debugged, which calls erlang:apply/2)
+ ?line {'EXIT',{{badarity,{F1,[]}},[{erlang,apply,_}|_]}} =
+ spawn_eval(fun() -> ?IM:do_apply(F1) end),
+
+ %% Error in fun
+ ?line {'EXIT',{snape,[{?MODULE,_FunName,_}|_]}} =
+ spawn_eval(fun() -> ?IM:do_apply(F1, snape) end),
+
+ ok.
+
+%%
+%% Try executing an interpreted exit/1 call.
+%%
+
+interpreted_exit(Config) when is_list(Config) ->
+ ?line process_flag(trap_exit, true),
+ ?line Reason = make_ref(),
+ ?line Pid = spawn_link(fun() -> ?IM:please_call_exit(Reason) end),
+ ?line receive
+ {'EXIT',Pid,Reason} ->
+ ok;
+ {'EXIT',Pid,BadReason} ->
+ ?line ?t:fail({bad_message,BadReason})
+ after 10000 ->
+ ?line ?t:fail(timeout)
+ end,
+ ok.
+
+otp_8310(doc) ->
+ "OTP-8310. Bugfixes lc/bc and andalso/orelse.";
+otp_8310(Config) when is_list(Config) ->
+ ?line ok = ?IM:otp_8310(),
+ ok.
+
+applier(M, F, A) ->
+ Res = apply(M, F, A),
+ io:format("~p:~p(~p) => ~p\n", [M,F,A,Res]),
+ Res.
+
+%%
+%% Evaluate in another process, to prevent the test_case process to become
+%% interpreted.
+%%
+
+spawn_eval(Fun) ->
+ Self = self(),
+ spawn_link(fun() -> Self ! (catch Fun()) end),
+ receive
+ Result ->
+ Result
+ end.
diff --git a/lib/debugger/test/int_eval_SUITE_data/Makefile.src b/lib/debugger/test/int_eval_SUITE_data/Makefile.src
new file mode 100644
index 0000000000..28a1432157
--- /dev/null
+++ b/lib/debugger/test/int_eval_SUITE_data/Makefile.src
@@ -0,0 +1,26 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2000-2010. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+
+
+EFLAGS=+debug_info
+
+all: my_int_eval_module.@EMULATOR@
+
+my_int_eval_module.@EMULATOR@: my_int_eval_module.erl
+ erlc $(EFLAGS) my_int_eval_module.erl
diff --git a/lib/debugger/test/int_eval_SUITE_data/my_int_eval_module.erl b/lib/debugger/test/int_eval_SUITE_data/my_int_eval_module.erl
new file mode 100644
index 0000000000..997ee6e17d
--- /dev/null
+++ b/lib/debugger/test/int_eval_SUITE_data/my_int_eval_module.erl
@@ -0,0 +1,245 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-module(my_int_eval_module).
+-stupid_attribute({a,b}).
+
+-export([ets_new/0,ets_delete/1,spawn_test/0,apply_test/1,external_call_test/1]).
+-export([check_exports/1,check_module_info/2]).
+-export([give_me_a_fun_0/0,give_me_a_fun_0/1,give_me_a_fun_1/2,
+ give_me_a_bad_fun/0, do_apply/1, do_apply/2]).
+-export([please_call_exit/1,i_will_do_the_exit/1]).
+-export([more_catch/1,more_nocatch/1,exit_me/0]).
+-export([f/1, f_try/1, f_catch/1]).
+-export([otp_5837/1, otp_8310/0]).
+
+%% Internal exports.
+-export([echo/2,my_subtract/2,catch_a_ball/0,throw_a_ball/0]).
+-export([i_am_exported/1]).
+
+-import(lists, [member/2]).
+
+-define(line,put(test_server_loc,{?MODULE,?LINE}),).
+-define(t,test_server).
+-define(m,test_server:match).
+-define(config,test_server:lookup_config).
+
+ets_new() ->
+ Id = ets:new(my_int_eval_table, [private]),
+ Id.
+
+ets_delete(Tab) ->
+ ets:delete(Tab).
+
+%% Spawning.
+
+spawn_test() ->
+ Term = {a,tuple},
+ Pid = spawn_link(?MODULE, echo, [self(),Term]),
+ receive
+ {result,Pid,Term} -> ok;
+ Other -> {bad_response,Other}
+ after 5000 ->
+ timeout
+ end.
+
+echo(Parent, Term) ->
+ Parent ! {result,self(),Term}.
+
+%% Applying.
+
+apply_test(Fun) ->
+ 42 = Fun(number(2), number(40)),
+ 12 = apply(Fun, [number(7),number(5)]),
+
+ Mod = module(),
+ Func = func(),
+ [a] = Mod:my_subtract(same([a,b,c]), same([b,c])),
+ [a,b] = Mod:Func(same([a,b,c]), same([c])),
+ [a,b,d] = ?MODULE:Func(same([a,b,c,d]), same([c])),
+ [d,e] = apply(Mod, Func, [same([d,e,f]), same([f])]),
+ [3] = apply(?MODULE, Func, [same([3,4]),same([4])]),
+
+ %% This is obsolete, but it should work anyway.
+ HomeMadeFun = {?MODULE,my_subtract},
+ [a] = HomeMadeFun(same([a,x,c]), same([x,c])),
+ [x] = apply(HomeMadeFun, [[x,y],[y,z]]),
+
+ ok.
+
+number(X) -> {number,X}.
+module() -> ?MODULE.
+func() -> my_subtract.
+same(X) -> X.
+
+my_subtract(X, Y) -> X -- Y.
+
+%% Catch and throw.
+
+catch_a_ball() ->
+ {a,ball} = (catch throw_a_ball()),
+ ok.
+
+throw_a_ball() ->
+ throw({a,ball}),
+ not_ok.
+
+exit_me() ->
+ exit({int,exit}).
+
+more_catch(Fun) ->
+ case catch lists:filter(Fun, [a]) of
+ {'EXIT', {_, exit}} ->
+ ok;
+ Else -> Else
+ end.
+
+more_nocatch(Fun) ->
+ lists:filter(Fun, [a]).
+
+%% External calls.
+
+external_call_test(Data) ->
+ {'EXIT',{undef,[{?MODULE,not_exported,[42,Data]}|_]}} =
+ (catch ?MODULE:not_exported(42, Data)),
+ {yes,Data} = i_am_exported(Data),
+ {yes,Data} = ?MODULE:i_am_exported(Data),
+
+ %% Excercise the function cache in the interpreter.
+
+ {ok,Data,[a,b]} = not_exported(Data, [a,b]),
+ {yes,Data} = i_am_exported(Data),
+ {ok,Data,[a,b]} = not_exported(Data, [a,b]),
+ {'EXIT',{undef,[{?MODULE,not_exported,[7,Data]}|_]}} =
+ (catch ?MODULE:not_exported(7, Data)),
+ {yes,Data} = ?MODULE:i_am_exported(Data),
+ ok.
+
+not_exported(N, D) ->
+ {ok,N,D}.
+
+i_am_exported(D) ->
+ {yes,D}.
+
+%% The module_info/0,1 functions and list comprehensions (funs).
+
+check_exports(Exp) ->
+ %% Check the structure of the export list and that there are more
+ %% than 4 elements.
+
+ Exp = [{F,A} || {F,A} <- Exp, erlang:is_atom(F), erlang:is_integer(A)],
+ case length(Exp) of
+ Len when Len > 4 -> ok
+ end.
+
+check_module_info(ModInfo, Exports) ->
+ ModInfo = module_info(),
+ Exports = module_info(exports),
+ ok.
+
+%% Testcase apply_interpreted_fun/1.
+
+give_me_a_fun_0() ->
+ fun() -> perfectly_alright end.
+
+give_me_a_fun_0(Term) ->
+ fun() -> {ok,Term} end.
+
+give_me_a_fun_1(Min, Max) ->
+ Seq = lists:seq(Min, Max),
+ fun (L) when list(L) ->
+ [Info || {Key,Info} <- L, lists:member(Key, Seq)];
+ (T) when tuple(T) ->
+ L = tuple_to_list(T),
+ F = fun({Key,Info}) ->
+ case lists:member(Key, Seq) of
+ true -> Info;
+ false -> false
+ end
+ end,
+ list_to_tuple(lists:map(F, L))
+ end.
+
+give_me_a_bad_fun() ->
+ fun(Arg) -> erlang:error(Arg) end.
+
+do_apply(Fun) ->
+ Fun().
+do_apply(Fun, Arg) ->
+ Fun(Arg).
+
+
+please_call_exit(Reason) ->
+ put(asked_to_call_exit, Reason),
+ put(will_call_my_good_friend, ''),
+ Res = int_eval_SUITE:applier(?MODULE, i_will_do_the_exit, [Reason]),
+
+ %% We don't want a tail-recursive call above.
+ io:format("Returned from exit/1 -- how strange\n").
+
+i_will_do_the_exit(Reason) ->
+ exit(Reason).
+
+f(Arg) ->
+ g(Arg).
+
+f_try(Arg) ->
+ try g(Arg)
+ catch
+ Class:Reason ->
+ {Class, Reason}
+ end.
+
+f_catch(Arg) ->
+ catch g(Arg).
+
+g({error, Reason}) ->
+ erlang:error(Reason);
+g({exit, Reason}) ->
+ erlang:exit(Reason);
+g({throw, Reason}) ->
+ erlang:throw(Reason);
+g(Value) ->
+ Value.
+
+otp_5837(N) ->
+ n(N).
+
+n(N) ->
+ lists:map(fun(X) when N==X ->
+ yes;
+ (_) ->
+ no
+ end,
+ [1,2,3,4]).
+
+otp_8310() ->
+ a = if (false orelse a) =:= a -> a; true -> b end,
+ F1 = fun() -> a end,
+ {'EXIT',{{bad_filter,a},_}} =
+ (catch {a, [X || X <- [1,2,3], _ = F1()]}),
+ F2 = fun() -> << 3:8 >> end,
+ {'EXIT',{{bad_filter,<<3>>},_}} =
+ (catch {a, << << X >> || << X >> <= << 7:8 >>,_ = F2() >>}),
+ {'EXIT',{{bad_generator,a},_}} =
+ (catch {a, [X || X <- a]}),
+ {'EXIT',{{bad_generator,b},_}} =
+ (catch {a, << <<X>> || << X >> <= b >>}),
+ ok.
diff --git a/lib/debugger/test/lc_SUITE.erl b/lib/debugger/test/lc_SUITE.erl
new file mode 100644
index 0000000000..a22a689ec8
--- /dev/null
+++ b/lib/debugger/test/lc_SUITE.erl
@@ -0,0 +1,74 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-module(lc_SUITE).
+
+-author('[email protected]').
+-export([all/1,init_per_testcase/2,fin_per_testcase/2,init_all/1,finish_all/1,
+ basic/1]).
+
+-include("test_server.hrl").
+
+all(suite) ->
+ [{conf,init_all,cases(),finish_all}].
+
+cases() ->
+ [basic].
+
+init_per_testcase(_Case, Config) ->
+ test_lib:interpret(?MODULE),
+ Dog = test_server:timetrap(?t:minutes(1)),
+ [{watchdog,Dog}|Config].
+
+fin_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+init_all(Config) when is_list(Config) ->
+ ?line test_lib:interpret(?MODULE),
+ ?line true = lists:member(?MODULE, int:interpreted()),
+ ok.
+
+finish_all(Config) when is_list(Config) ->
+ ok.
+
+basic(Config) when list(Config) ->
+ ?line L0 = lists:seq(1, 10),
+ ?line L1 = my_map(fun(X) -> {x,X} end, L0),
+ ?line L1 = [{x,X} || X <- L0],
+ ?line L0 = my_map(fun({x,X}) -> X end, L1),
+ ?line [1,2,3,4,5] = [X || X <- L0, X < 6],
+ ?line [4,5,6] = [X || X <- L0, X > 3, X < 7],
+ ?line [] = [X || X <- L0, X > 32, X < 7],
+ ?line [1,3,5,7,9] = [X || X <- L0, odd(X)],
+
+ %% Error cases.
+ ?line [] = [X || X <- L1, X+1 < 2],
+ ?line [] = [{xx,X} || X <- L0, element(2, X) == no_no_no],
+ ?line {'EXIT',_} = (catch [X || X <- L1, odd(X)]),
+
+ ok.
+
+my_map(F, L) ->
+ [F(X) || X <- L].
+
+odd(X) ->
+ X rem 2 == 1.
diff --git a/lib/debugger/test/record_SUITE.erl b/lib/debugger/test/record_SUITE.erl
new file mode 100644
index 0000000000..06fd01555e
--- /dev/null
+++ b/lib/debugger/test/record_SUITE.erl
@@ -0,0 +1,252 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%% Purpose : Test records.
+
+-module(record_SUITE).
+
+-include("test_server.hrl").
+
+-export([all/1,init_per_testcase/2,fin_per_testcase/2,init_all/1,finish_all/1,
+ errors/1,record_test/1,eval_once/1]).
+
+all(suite) ->
+ [{conf,init_all,cases(),finish_all}].
+
+cases() ->
+ [errors,record_test,eval_once].
+
+init_per_testcase(_Case, Config) ->
+ test_lib:interpret(?MODULE),
+ Dog = test_server:timetrap(?t:minutes(1)),
+ [{watchdog,Dog}|Config].
+
+fin_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+init_all(Config) when is_list(Config) ->
+ ?line test_lib:interpret(?MODULE),
+ ?line true = lists:member(?MODULE, int:interpreted()),
+ ok.
+
+finish_all(Config) when is_list(Config) ->
+ ok.
+
+-record(foo, {a,b,c,d}).
+-record(bar, {a,b,c,d}).
+-record(barf, {a,b,c,d,e}).
+
+errors(Config) when is_list(Config) ->
+ Foo = #foo{a=1,b=2,c=3,d=4},
+ ?line #foo{a=19,b=42,c=3,d=4} = update_foo(Foo, 19, 42),
+
+ ?line {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19)),
+ ?line {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19, 35)),
+ ?line {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19, 35, 17)),
+ ?line {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19, 35, 17, 42)),
+
+ ?line {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19)),
+ ?line {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, 35)),
+ ?line {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, 35, 17)),
+ ?line {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, 35, 17, 42)),
+ ?line {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19,
+ 35, 17, 42, -2)),
+
+ ok.
+
+update_foo(#foo{}=R, A, B) ->
+ R#foo{a=A,b=B}.
+
+update_foo_bar(#foo{}=R, A) ->
+ R#bar{a=A}.
+
+update_foo_bar(#foo{}=R, A, _B) ->
+ R#bar{a=A,b=A}.
+
+update_foo_bar(#foo{}=R, A, _B, C) ->
+ R#bar{a=A,b=A,c=C}.
+
+update_foo_bar(#foo{}=R, A, _B, C, D) ->
+ R#bar{a=A,b=A,c=C,d=D}.
+
+update_foo_barf(#foo{}=R, A) ->
+ R#barf{a=A}.
+
+update_foo_barf(#foo{}=R, A, _B) ->
+ R#barf{a=A,b=A}.
+
+update_foo_barf(#foo{}=R, A, _B, C) ->
+ R#barf{a=A,b=A,c=C}.
+
+update_foo_barf(#foo{}=R, A, _B, C, D) ->
+ R#barf{a=A,b=A,c=C,d=D}.
+
+update_foo_barf(#foo{}=R, A, _B, C, D, E) ->
+ R#barf{a=A,b=A,c=C,d=D,e=E}.
+
+
+-define(TrueGuard(Expr), if Expr -> ok; true -> ?t:fail() end).
+-define(FalseGuard(Expr), if Expr -> ?t:fail(); true -> ok end).
+
+record_test(Config) when is_list(Config) ->
+ ?line true = is_record(#foo{}, foo),
+ ?line false = is_record(#foo{}, barf),
+ ?line false = is_record({foo}, foo),
+
+ ?line true = erlang:is_record(#foo{}, foo),
+ ?line false = erlang:is_record(#foo{}, barf),
+ ?line false = erlang:is_record({foo}, foo),
+
+ ?line false = is_record([], foo),
+ ?line false = is_record(Config, foo),
+
+ ?line ?TrueGuard(is_record(#foo{}, foo)),
+ ?line ?FalseGuard(is_record(#foo{}, barf)),
+ ?line ?FalseGuard(is_record({foo}, foo)),
+
+ ?line ?TrueGuard(erlang:is_record(#foo{}, foo)),
+ ?line ?FalseGuard(erlang:is_record(#foo{}, barf)),
+ ?line ?FalseGuard(erlang:is_record({foo}, foo)),
+
+ ?line ?FalseGuard(is_record([], foo)),
+ ?line ?FalseGuard(is_record(Config, foo)),
+
+ %% 'not is_record/2' to test guard optimization.
+
+ ?line ?FalseGuard(not is_record(#foo{}, foo)),
+ ?line ?TrueGuard(not is_record(#foo{}, barf)),
+ ?line ?TrueGuard(not is_record({foo}, foo)),
+
+ ?line ?FalseGuard(not erlang:is_record(#foo{}, foo)),
+ ?line ?TrueGuard(not erlang:is_record(#foo{}, barf)),
+ ?line ?TrueGuard(not erlang:is_record({foo}, foo)),
+
+ Foo = id(#foo{}),
+ ?line ?FalseGuard(not erlang:is_record(Foo, foo)),
+ ?line ?TrueGuard(not erlang:is_record(Foo, barf)),
+
+ ?line ?TrueGuard(not is_record(Config, foo)),
+
+ ?line ?TrueGuard(not is_record(a, foo)),
+ ?line ?TrueGuard(not is_record([], foo)),
+
+ %% Pass non-literal first argument.
+
+ ?line true = is_record(id(#foo{}), foo),
+ ?line false = is_record(id(#foo{}), barf),
+ ?line false = is_record(id({foo}), foo),
+
+ ?line true = erlang:is_record(id(#foo{}), foo),
+ ?line false = erlang:is_record(id(#foo{}), barf),
+ ?line false = erlang:is_record(id({foo}), foo),
+
+ NoRec1 = id(blurf),
+ NoRec2 = id([]),
+
+ ?line ?TrueGuard(not is_record(NoRec1, foo)),
+ ?line ?TrueGuard(not is_record(NoRec2, foo)),
+
+ %% Force the use of guard bifs by using the 'xor' operation.
+
+ False = id(false),
+ ?line ?TrueGuard(is_record(#foo{}, foo) xor False),
+ ?line ?FalseGuard(is_record(#foo{}, barf) xor False),
+ ?line ?FalseGuard(is_record({foo}, foo) xor False ),
+
+ ?line ?TrueGuard(is_record(Foo, foo) xor False),
+ ?line ?FalseGuard(is_record(Foo, barf) xor False),
+
+
+ %% Implicit guards by using a list comprehension.
+
+ List = id([1,#foo{a=2},3,#bar{d=4},5,#foo{a=6},7]),
+
+ ?line [#foo{a=2},#foo{a=6}] = [X || X <- List, is_record(X, foo)],
+ ?line [#bar{d=4}] = [X || X <- List, is_record(X, bar)],
+ ?line [1,#foo{a=2},3,5,#foo{a=6},7] =
+ [X || X <- List, not is_record(X, bar)],
+ ?line [1,3,5,7] =
+ [X || X <- List, ((not is_record(X, bar)) and (not is_record(X, foo)))],
+ ?line [#foo{a=2},#bar{d=4},#foo{a=6}] =
+ [X || X <- List, ((is_record(X, bar)) or (is_record(X, foo)))],
+ ?line [1,3,#bar{d=4}] =
+ [X || X <- List, ((is_record(X, bar)) or (X < 5))],
+
+ ?line MyList = [#foo{a=3},x,[],{a,b}],
+ ?line [#foo{a=3}] = [X || X <- MyList, is_record(X, foo)],
+ ?line [x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo)],
+ ?line [#foo{a=3}] = [X || X <- MyList, begin is_record(X, foo) end],
+ ?line [x,[],{a,b}] = [X || X <- MyList, begin not is_record(X, foo) end],
+ ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, is_record(X, foo) or
+ not is_binary(X)],
+ ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo) or
+ not is_binary(X)],
+ ?line [#foo{a=3}] = [X || X <- MyList, is_record(X, foo) or is_reference(X)],
+ ?line [x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo) or
+ is_reference(X)],
+ ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList,
+ begin is_record(X, foo) or
+ not is_binary(X) end],
+ ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList,
+ begin not is_record(X, foo) or
+ not is_binary(X) end],
+ ?line [#foo{a=3}] = [X || X <- MyList,
+ begin is_record(X, foo) or is_reference(X) end],
+ ?line [x,[],{a,b}] = [X || X <- MyList,
+ begin not is_record(X, foo) or
+ is_reference(X) end],
+ ok.
+
+eval_once(Config) when is_list(Config) ->
+ ?line once(fun(GetRec) ->
+ true = erlang:is_record(GetRec(), foo)
+ end, #foo{}),
+ ?line once(fun(GetRec) ->
+ (GetRec())#foo{a=1}
+ end, #foo{}),
+ ?line once(fun(GetRec) ->
+ (GetRec())#foo{a=1,b=2}
+ end, #foo{}),
+ ?line once(fun(GetRec) ->
+ (GetRec())#foo{a=1,b=2,c=3}
+ end, #foo{}),
+ ?line once(fun(GetRec) ->
+ (GetRec())#foo{a=1,b=2,c=3,d=4}
+ end, #foo{}),
+ ok.
+
+once(Test, Record) ->
+ put(?MODULE, 0),
+ GetRec = fun() ->
+ put(?MODULE, 1+get(?MODULE)),
+ Record
+ end,
+ Result = Test(GetRec),
+ case get(?MODULE) of
+ 1 -> ok;
+ N ->
+ io:format("Evaluated ~w times\n", [N]),
+ ?t:fail()
+ end,
+ Result.
+
+id(I) -> I.
diff --git a/lib/debugger/test/test_lib.erl b/lib/debugger/test/test_lib.erl
new file mode 100644
index 0000000000..541375e64a
--- /dev/null
+++ b/lib/debugger/test/test_lib.erl
@@ -0,0 +1,29 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2000-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+
+-module(test_lib).
+
+-export([interpret/1]).
+
+interpret(Mod) when atom(Mod) ->
+ case lists:member(Mod, int:interpreted()) of
+ true -> ok;
+ false -> {module,Mod} = i:ii(Mod)
+ end.
diff --git a/lib/debugger/test/trycatch_SUITE.erl b/lib/debugger/test/trycatch_SUITE.erl
new file mode 100644
index 0000000000..5901cdc9e5
--- /dev/null
+++ b/lib/debugger/test/trycatch_SUITE.erl
@@ -0,0 +1,796 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-module(trycatch_SUITE).
+
+-export([all/1,init_per_testcase/2,fin_per_testcase/2,init_all/1,finish_all/1,
+ basic/1,lean_throw/1,try_of/1,try_after/1,%after_bind/1,
+ catch_oops/1,after_oops/1,eclectic/1,rethrow/1,
+ nested_of/1,nested_catch/1,nested_after/1]).
+
+-include("test_server.hrl").
+
+all(suite) ->
+ [{conf,init_all,cases(),finish_all}].
+
+cases() ->
+ [basic,lean_throw,try_of,try_after,%after_bind,
+ catch_oops,after_oops,eclectic,rethrow,
+ nested_of,nested_catch,nested_after].
+
+init_per_testcase(_Case, Config) ->
+ test_lib:interpret(?MODULE),
+ Dog = test_server:timetrap(?t:minutes(1)),
+ [{watchdog,Dog}|Config].
+
+fin_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+init_all(Config) when is_list(Config) ->
+ ?line test_lib:interpret(?MODULE),
+ ?line true = lists:member(?MODULE, int:interpreted()),
+ ok.
+
+finish_all(Config) when is_list(Config) ->
+ ok.
+
+basic(Conf) when is_list(Conf) ->
+ ?line 2 =
+ try my_div(4, 2)
+ catch
+ Class:Reason -> {Class,Reason}
+ end,
+ ?line error =
+ try my_div(1, 0)
+ catch
+ error:badarith -> error
+ end,
+ ?line error =
+ try 1/0
+ catch
+ error:badarith -> error
+ end,
+ ?line ok =
+ try my_add(53, atom)
+ catch
+ error:badarith -> ok
+ end,
+ ?line exit_nisse =
+ try exit(nisse)
+ catch
+ exit:nisse -> exit_nisse
+ end,
+ ?line ok =
+ try throw(kalle)
+ catch
+ kalle -> ok
+ end,
+
+ %% Try some stuff where the compiler will optimize away the try.
+
+ V = id({a,variable}),
+ ?line V = try V catch nisse -> error end,
+ ?line 42 = try 42 catch nisse -> error end,
+ ?line [V] = try [V] catch nisse -> error end,
+ ?line {ok,V} = try {ok,V} catch nisse -> error end,
+
+ %% Same idea, but use an after too.
+
+ ?line V = try V catch nisse -> error after after_call() end,
+ ?line after_clean(),
+ ?line 42 = try 42 after after_call() end,
+ ?line after_clean(),
+ ?line [V] = try [V] catch nisse -> error after after_call() end,
+ ?line after_clean(),
+ ?line {ok,V} = try {ok,V} after after_call() end,
+
+ %% Try/of
+ ?line ok = try V of
+ {a,variable} -> ok
+ catch nisse -> erro
+ end,
+
+ ok.
+
+after_call() ->
+ put(basic, after_was_called).
+
+after_clean() ->
+ after_was_called = erase(basic).
+
+lean_throw(Conf) when is_list(Conf) ->
+ ?line {throw,kalle} =
+ try throw(kalle)
+ catch
+ Kalle -> {throw,Kalle}
+ end,
+ ?line {exit,kalle} =
+ try exit(kalle)
+ catch
+ Throw1 -> {throw,Throw1};
+ exit:Reason1 -> {exit,Reason1}
+ end,
+ ?line {exit,kalle} =
+ try exit(kalle)
+ catch
+ exit:Reason2 -> {exit,Reason2};
+ Throw2 -> {throw,Throw2}
+ end,
+ ?line {exit,kalle} =
+ try try exit(kalle)
+ catch
+ Throw3 -> {throw,Throw3}
+ end
+ catch
+ exit:Reason3 -> {exit,Reason3}
+ end,
+ ok.
+
+try_of(Conf) when is_list(Conf) ->
+ ?line {ok,{some,content}} =
+ try_of_1({value,{good,{some,content}}}),
+ ?line {error,[other,content]} =
+ try_of_1({value,{bad,[other,content]}}),
+ ?line {caught,{exit,{ex,it,[reason]}}} =
+ try_of_1({exit,{ex,it,[reason]}}),
+ ?line {caught,{throw,[term,{in,a,{tuple}}]}} =
+ try_of_1({throw,[term,{in,a,{tuple}}]}),
+ ?line {caught,{error,[bad,arg]}} =
+ try_of_1({error,[bad,arg]}),
+ ?line {caught,{error,badarith}} =
+ try_of_1({'div',{1,0}}),
+ ?line {caught,{error,badarith}} =
+ try_of_1({'add',{a,0}}),
+ ?line {caught,{error,badarg}} =
+ try_of_1({'abs',x}),
+ ?line {caught,{error,function_clause}} =
+ try_of_1(illegal),
+ ?line {error,{try_clause,{some,other_garbage}}} =
+ try try_of_1({value,{some,other_garbage}})
+ catch error:Reason -> {error,Reason}
+ end,
+ ok.
+
+try_of_1(X) ->
+ try foo(X) of
+ {good,Y} -> {ok,Y};
+ {bad,Y} -> {error,Y}
+ catch
+ Class:Reason ->
+ {caught,{Class,Reason}}
+ end.
+
+try_after(Conf) when is_list(Conf) ->
+ ?line {{ok,[some,value],undefined},finalized} =
+ try_after_1({value,{ok,[some,value]}},finalized),
+ ?line {{error,badarith,undefined},finalized} =
+ try_after_1({'div',{1,0}},finalized),
+ ?line {{error,badarith,undefined},finalized} =
+ try_after_1({'add',{1,a}},finalized),
+ ?line {{error,badarg,undefined},finalized} =
+ try_after_1({'abs',a},finalized),
+ ?line {{error,[the,{reason}],undefined},finalized} =
+ try_after_1({error,[the,{reason}]},finalized),
+ ?line {{throw,{thrown,[reason]},undefined},finalized} =
+ try_after_1({throw,{thrown,[reason]}},finalized),
+ ?line {{exit,{exited,{reason}},undefined},finalized} =
+ try_after_1({exit,{exited,{reason}}},finalized),
+ ?line {{error,function_clause,undefined},finalized} =
+ try_after_1(function_clause,finalized),
+ ?line ok =
+ try try_after_1({'add',{1,1}}, finalized)
+ catch
+ error:{try_clause,2} -> ok
+ end,
+ ?line finalized = erase(try_after),
+ ?line ok =
+ try try foo({exit,[reaso,{n}]})
+ after put(try_after, finalized)
+ end
+ catch
+ exit:[reaso,{n}] -> ok
+ end,
+ ok.
+
+try_after_1(X, Y) ->
+ erase(try_after),
+ Try =
+ try foo(X) of
+ {ok,Value} -> {ok,Value,get(try_after)}
+ catch
+ Reason -> {throw,Reason,get(try_after)};
+ error:Reason -> {error,Reason,get(try_after)};
+ exit:Reason -> {exit,Reason,get(try_after)}
+ after
+ put(try_after, Y)
+ end,
+ {Try,erase(try_after)}.
+
+-ifdef(begone).
+
+after_bind(Conf) when is_list(Conf) ->
+ V = [make_ref(),self()|value],
+ ?line {value,{value,V}} =
+ after_bind_1({value,V}, V, {value,V}),
+ ok.
+
+after_bind_1(X, V, Y) ->
+ try
+ Try =
+ try foo(X) of
+ V -> value
+ catch
+ C1:V -> {caught,C1}
+ after
+ After = foo(Y)
+ end,
+ {Try,After}
+ of
+ V -> {value,V}
+ catch
+ C:D -> {caught,{C,D}}
+ end.
+
+-endif.
+
+catch_oops(Conf) when is_list(Conf) ->
+ V = {v,[a,l|u],{e},self()},
+ ?line {value,V} = catch_oops_1({value,V}),
+ ?line {value,1} = catch_oops_1({'div',{1,1}}),
+ ?line {error,badarith} = catch_oops_1({'div',{1,0}}),
+ ?line {error,function_clause} = catch_oops_1(function_clause),
+ ?line {throw,V} = catch_oops_1({throw,V}),
+ ?line {exit,V} = catch_oops_1({exit,V}),
+ ok.
+
+catch_oops_1(X) ->
+ Ref = make_ref(),
+ try try foo({error,Ref})
+ catch
+ error:Ref ->
+ foo(X)
+ end of
+ Value -> {value,Value}
+ catch
+ Class:Data -> {Class,Data}
+ end.
+
+
+
+after_oops(Conf) when is_list(Conf) ->
+ V = {self(),make_ref()},
+ ?line {{value,V},V} = after_oops_1({value,V}, {value,V}),
+ ?line {{exit,V},V} = after_oops_1({exit,V}, {value,V}),
+ ?line {{error,V},undefined} = after_oops_1({value,V}, {error,V}),
+ ?line {{error,function_clause},undefined} =
+ after_oops_1({exit,V}, function_clause),
+ ok.
+
+after_oops_1(X, Y) ->
+ erase(after_oops),
+ Try =
+ try try foo(X)
+ after
+ put(after_oops, foo(Y))
+ end of
+ V -> {value,V}
+ catch
+ C:D -> {C,D}
+ end,
+ {Try,erase(after_oops)}.
+
+
+
+eclectic(Conf) when is_list(Conf) ->
+ V = {make_ref(),3.1415926535,[[]|{}]},
+ ?line {{value,{value,V},V},V} =
+ eclectic_1({foo,{value,{value,V}}}, undefined, {value,V}),
+ ?line {{'EXIT',{V,[{?MODULE,foo,_}|_]}},V} =
+ eclectic_1({catch_foo,{error,V}}, undefined, {value,V}),
+ ?line {{error,{exit,V},{'EXIT',V}},V} =
+ eclectic_1({foo,{error,{exit,V}}}, error, {value,V}),
+ ?line {{value,{value,V},V},{'EXIT',{badarith,[{?MODULE,my_add,_}|_]}}} =
+ eclectic_1({foo,{value,{value,V}}}, undefined, {'add',{0,a}}),
+ ?line {{'EXIT',V},V} =
+ eclectic_1({catch_foo,{exit,V}}, undefined, {throw,V}),
+ ?line {{error,{'div',{1,0}},{'EXIT',{badarith,[{?MODULE,my_div,_}|_]}}}, {'EXIT',V}} =
+ eclectic_1({foo,{error,{'div',{1,0}}}}, error, {exit,V}),
+ ?line {{{error,V},{'EXIT',{V,[{?MODULE,foo,_}|_]}}},{'EXIT',V}} =
+ eclectic_1({catch_foo,{throw,{error,V}}}, undefined, {exit,V}),
+ %%
+ ?line {{value,{value,{value,V},V}},V} =
+ eclectic_2({value,{value,V}}, undefined, {value,V}),
+ ?line {{value,{throw,{value,V},V}},V} =
+ eclectic_2({throw,{value,V}}, throw, {value,V}),
+ ?line {{caught,{'EXIT',V}},undefined} =
+ eclectic_2({value,{value,V}}, undefined, {exit,V}),
+ ?line {{caught,{'EXIT',{V,[{?MODULE,foo,_}|_]}}},undefined} =
+ eclectic_2({error,{value,V}}, throw, {error,V}),
+ ?line {{caught,{'EXIT',{badarg,[{erlang,abs,[V]}|_]}}},V} =
+ eclectic_2({value,{'abs',V}}, undefined, {value,V}),
+ ?line {{caught,{'EXIT',{badarith,[{?MODULE,my_add,_}|_]}}},V} =
+ eclectic_2({exit,{'add',{0,a}}}, exit, {value,V}),
+ ?line {{caught,{'EXIT',V}},undefined} =
+ eclectic_2({value,{error,V}}, undefined, {exit,V}),
+ ?line {{caught,{'EXIT',{V,[{?MODULE,foo,_}|_]}}},undefined} =
+ eclectic_2({throw,{'div',{1,0}}}, throw, {error,V}),
+ ok.
+
+eclectic_1(X, C, Y) ->
+ erase(eclectic),
+ Done = make_ref(),
+ Try =
+ try case X of
+ {catch_foo,V} -> catch {Done,foo(V)};
+ {foo,V} -> {Done,foo(V)}
+ end of
+ {Done,D} -> {value,D,catch foo(D)};
+ {'EXIT',_}=Exit -> Exit;
+ D -> {D,catch foo(D)}
+ catch
+ C:D -> {C,D,catch foo(D)}
+ after
+ put(eclectic, catch foo(Y))
+ end,
+ {Try,erase(eclectic)}.
+
+eclectic_2(X, C, Y) ->
+ Done = make_ref(),
+ erase(eclectic),
+ Catch =
+ case
+ catch
+ {Done,
+ try foo(X) of
+ V -> {value,V,foo(V)}
+ catch
+ C:D -> {C,D,foo(D)}
+ after
+ put(eclectic, foo(Y))
+ end} of
+ {Done,Z} -> {value,Z};
+ Z -> {caught,Z}
+ end,
+ {Catch,erase(eclectic)}.
+
+rethrow(Conf) when is_list(Conf) ->
+ V = {a,[b,{c,self()},make_ref]},
+ ?line {value2,value1} =
+ rethrow_1({value,V}, V),
+ ?line {caught2,{error,V}} =
+ rethrow_2({error,V}, undefined),
+ ?line {caught2,{exit,V}} =
+ rethrow_1({exit,V}, error),
+ ?line {caught2,{throw,V}} =
+ rethrow_1({throw,V}, undefined),
+ ?line {caught2,{throw,V}} =
+ rethrow_2({throw,V}, undefined),
+ ?line {caught2,{error,badarith}} =
+ rethrow_1({'add',{0,a}}, throw),
+ ?line {caught2,{error,function_clause}} =
+ rethrow_2(function_clause, undefined),
+ ?line {caught2,{error,{try_clause,V}}} =
+ rethrow_1({value,V}, exit),
+ ?line {value2,{caught1,V}} =
+ rethrow_1({error,V}, error),
+ ?line {value2,{caught1,V}} =
+ rethrow_1({exit,V}, exit),
+ ?line {value2,caught1} =
+ rethrow_2({throw,V}, V),
+ ok.
+
+rethrow_1(X, C1) ->
+ try try foo(X) of
+ C1 -> value1
+ catch
+ C1:D1 -> {caught1,D1}
+ end of
+ V2 -> {value2,V2}
+ catch
+ C2:D2 -> {caught2,{C2,D2}}
+ end.
+
+rethrow_2(X, C1) ->
+ try try foo(X) of
+ C1 -> value1
+ catch
+ C1 -> caught1 % Implicit class throw:
+ end of
+ V2 -> {value2,V2}
+ catch
+ C2:D2 -> {caught2,{C2,D2}}
+ end.
+
+
+
+nested_of(Conf) when is_list(Conf) ->
+ V = {[self()|make_ref()],1.4142136},
+ ?line {{value,{value1,{V,x2}}},
+ {V,x3},
+ {V,x4},
+ finalized} =
+ nested_of_1({{value,{V,x1}},void,{V,x1}},
+ {value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}),
+ ?line {{caught,{throw,{V,x2}}},
+ {V,x3},
+ {V,x4},
+ finalized} =
+ nested_of_1({{value,{V,x1}},void,{V,x1}},
+ {throw,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}),
+ ?line {{caught,{error,badarith}},
+ undefined,
+ {V,x4},
+ finalized} =
+ nested_of_1({{value,{V,x1}},void,{V,x1}},
+ {throw,{V,x2}}, {'div',{1,0}}, {value,{V,x4}}),
+ ?line {{caught,{error,badarith}},
+ undefined,
+ undefined,
+ finalized} =
+ nested_of_1({{value,{V,x1}},void,{V,x1}},
+ {throw,{V,x2}}, {'div',{1,0}}, {'add',{0,b}}),
+ %%
+ ?line {{caught,{error,{try_clause,{V,x1}}}},
+ {V,x3},
+ {V,x4},
+ finalized} =
+ nested_of_1({{value,{V,x1}},void,try_clause},
+ void, {value,{V,x3}}, {value,{V,x4}}),
+ ?line {{caught,{exit,{V,x3}}},
+ undefined,
+ {V,x4},
+ finalized} =
+ nested_of_1({{value,{V,x1}},void,try_clause},
+ void, {exit,{V,x3}}, {value,{V,x4}}),
+ ?line {{caught,{throw,{V,x4}}},
+ undefined,
+ undefined,
+ finalized} =
+ nested_of_1({{value,{V,x1}},void,try_clause},
+ void, {exit,{V,x3}}, {throw,{V,x4}}),
+ %%
+ ?line {{value,{caught1,{V,x2}}},
+ {V,x3},
+ {V,x4},
+ finalized} =
+ nested_of_1({{error,{V,x1}},error,{V,x1}},
+ {value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}),
+ ?line {{caught,{error,badarith}},
+ {V,x3},
+ {V,x4},
+ finalized} =
+ nested_of_1({{error,{V,x1}},error,{V,x1}},
+ {'add',{1,c}}, {value,{V,x3}}, {value,{V,x4}}),
+ ?line {{caught,{error,badarith}},
+ undefined,
+ {V,x4},
+ finalized} =
+ nested_of_1({{error,{V,x1}},error,{V,x1}},
+ {'add',{1,c}}, {'div',{17,0}}, {value,{V,x4}}),
+ ?line {{caught,{error,badarg}},
+ undefined,
+ undefined,
+ finalized} =
+ nested_of_1({{error,{V,x1}},error,{V,x1}},
+ {'add',{1,c}}, {'div',{17,0}}, {'abs',V}),
+ %%
+ ?line {{caught,{error,badarith}},
+ {V,x3},
+ {V,x4},
+ finalized} =
+ nested_of_1({{'add',{2,c}},rethrow,void},
+ void, {value,{V,x3}}, {value,{V,x4}}),
+ ?line {{caught,{error,badarg}},
+ undefined,
+ {V,x4},
+ finalized} =
+ nested_of_1({{'add',{2,c}},rethrow,void},
+ void, {'abs',V}, {value,{V,x4}}),
+ ?line {{caught,{error,function_clause}},
+ undefined,
+ undefined,
+ finalized} =
+ nested_of_1({{'add',{2,c}},rethrow,void},
+ void, {'abs',V}, function_clause),
+ ok.
+
+nested_of_1({X1,C1,V1},
+ X2, X3, X4) ->
+ erase(nested3),
+ erase(nested4),
+ erase(nested),
+ Self = self(),
+ Try =
+ try
+ try self()
+ of
+ Self ->
+ try
+ foo(X1)
+ of
+ V1 -> {value1,foo(X2)}
+ catch
+ C1:V1 -> {caught1,foo(X2)}
+ after
+ put(nested3, foo(X3))
+ end
+ after
+ put(nested4, foo(X4))
+ end
+ of
+ V -> {value,V}
+ catch
+ C:D -> {caught,{C,D}}
+ after
+ put(nested, finalized)
+ end,
+ {Try,erase(nested3),erase(nested4),erase(nested)}.
+
+
+
+nested_catch(Conf) when is_list(Conf) ->
+ V = {[make_ref(),1.4142136,self()]},
+ ?line {{value,{value1,{V,x2}}},
+ {V,x3},
+ {V,x4},
+ finalized} =
+ nested_catch_1({{value,{V,x1}},void,{V,x1}},
+ {value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}),
+ ?line {{caught,{throw,{V,x2}}},
+ {V,x3},
+ {V,x4},
+ finalized} =
+ nested_catch_1({{value,{V,x1}},void,{V,x1}},
+ {throw,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}),
+ ?line {{caught,{error,badarith}},
+ undefined,
+ {V,x4},
+ finalized} =
+ nested_catch_1({{value,{V,x1}},void,{V,x1}},
+ {throw,{V,x2}}, {'div',{1,0}}, {value,{V,x4}}),
+ ?line {{caught,{error,badarith}},
+ undefined,
+ undefined,
+ finalized} =
+ nested_catch_1({{value,{V,x1}},void,{V,x1}},
+ {throw,{V,x2}}, {'div',{1,0}}, {'add',{0,b}}),
+ %%
+ ?line {{caught,{error,{try_clause,{V,x1}}}},
+ {V,x3},
+ {V,x4},
+ finalized} =
+ nested_catch_1({{value,{V,x1}},void,try_clause},
+ void, {value,{V,x3}}, {value,{V,x4}}),
+ ?line {{caught,{exit,{V,x3}}},
+ undefined,
+ {V,x4},
+ finalized} =
+ nested_catch_1({{value,{V,x1}},void,try_clause},
+ void, {exit,{V,x3}}, {value,{V,x4}}),
+ ?line {{caught,{throw,{V,x4}}},
+ undefined,
+ undefined,
+ finalized} =
+ nested_catch_1({{value,{V,x1}},void,try_clause},
+ void, {exit,{V,x3}}, {throw,{V,x4}}),
+ %%
+ ?line {{value,{caught1,{V,x2}}},
+ {V,x3},
+ {V,x4},
+ finalized} =
+ nested_catch_1({{error,{V,x1}},error,{V,x1}},
+ {value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}),
+ ?line {{caught,{error,badarith}},
+ {V,x3},
+ {V,x4},
+ finalized} =
+ nested_catch_1({{error,{V,x1}},error,{V,x1}},
+ {'add',{1,c}}, {value,{V,x3}}, {value,{V,x4}}),
+ ?line {{caught,{error,badarith}},
+ undefined,
+ {V,x4},
+ finalized} =
+ nested_catch_1({{error,{V,x1}},error,{V,x1}},
+ {'add',{1,c}}, {'div',{17,0}}, {value,{V,x4}}),
+ ?line {{caught,{error,badarg}},
+ undefined,
+ undefined,
+ finalized} =
+ nested_catch_1({{error,{V,x1}},error,{V,x1}},
+ {'add',{1,c}}, {'div',{17,0}}, {'abs',V}),
+ %%
+ ?line {{caught,{error,badarith}},
+ {V,x3},
+ {V,x4},
+ finalized} =
+ nested_catch_1({{'add',{2,c}},rethrow,void},
+ void, {value,{V,x3}}, {value,{V,x4}}),
+ ?line {{caught,{error,badarg}},
+ undefined,
+ {V,x4},
+ finalized} =
+ nested_catch_1({{'add',{2,c}},rethrow,void},
+ void, {'abs',V}, {value,{V,x4}}),
+ ?line {{caught,{error,function_clause}},
+ undefined,
+ undefined,
+ finalized} =
+ nested_catch_1({{'add',{2,c}},rethrow,void},
+ void, {'abs',V}, function_clause),
+ ok.
+
+nested_catch_1({X1,C1,V1},
+ X2, X3, X4) ->
+ erase(nested3),
+ erase(nested4),
+ erase(nested),
+ Throw = make_ref(),
+ Try =
+ try
+ try throw(Throw)
+ catch
+ Throw ->
+ try
+ foo(X1)
+ of
+ V1 -> {value1,foo(X2)}
+ catch
+ C1:V1 -> {caught1,foo(X2)}
+ after
+ put(nested3, foo(X3))
+ end
+ after
+ put(nested4, foo(X4))
+ end
+ of
+ V -> {value,V}
+ catch
+ C:D -> {caught,{C,D}}
+ after
+ put(nested, finalized)
+ end,
+ {Try,erase(nested3),erase(nested4),erase(nested)}.
+
+nested_after(Conf) when is_list(Conf) ->
+ V = [{make_ref(),1.4142136,self()}],
+ ?line {value,
+ {V,x3},
+ {value1,{V,x2}},
+ finalized} =
+ nested_after_1({{value,{V,x1}},void,{V,x1}},
+ {value,{V,x2}}, {value,{V,x3}}),
+ ?line {{caught,{error,{V,x2}}},
+ {V,x3},
+ undefined,
+ finalized} =
+ nested_after_1({{value,{V,x1}},void,{V,x1}},
+ {error,{V,x2}}, {value,{V,x3}}),
+ ?line {{caught,{exit,{V,x3}}},
+ undefined,
+ undefined,
+ finalized} =
+ nested_after_1({{value,{V,x1}},void,{V,x1}},
+ {error,{V,x2}}, {exit,{V,x3}}),
+ %%
+ ?line {{caught,{error,{try_clause,{V,x1}}}},
+ {V,x3},
+ undefined,
+ finalized} =
+ nested_after_1({{value,{V,x1}},void,try_clause},
+ void, {value,{V,x3}}),
+ ?line {{caught,{error,badarith}},
+ undefined,
+ undefined,
+ finalized} =
+ nested_after_1({{value,{V,x1}},void,try_clause},
+ void, {'div',{17,0}}),
+ %%
+ ?line {value,
+ {V,x3},
+ {caught1,{V,x2}},
+ finalized} =
+ nested_after_1({{throw,{V,x1}},throw,{V,x1}},
+ {value,{V,x2}}, {value,{V,x3}}),
+ ?line {{caught,{error,badarith}},
+ {V,x3},
+ undefined,
+ finalized} =
+ nested_after_1({{throw,{V,x1}},throw,{V,x1}},
+ {'add',{a,b}}, {value,{V,x3}}),
+ ?line {{caught,{error,badarg}},
+ undefined,
+ undefined,
+ finalized} =
+ nested_after_1({{throw,{V,x1}},throw,{V,x1}},
+ {'add',{a,b}}, {'abs',V}),
+ %%
+ ?line {{caught,{throw,{V,x1}}},
+ {V,x3},
+ undefined,
+ finalized} =
+ nested_after_1({{throw,{V,x1}},rethrow,void},
+ void, {value,{V,x3}}),
+ ?line {{caught,{error,badarith}},
+ undefined,
+ undefined,
+ finalized} =
+ nested_after_1({{throw,{V,x1}},rethrow,void},
+ void, {'div',{1,0}}),
+ ok.
+
+nested_after_1({X1,C1,V1},
+ X2, X3) ->
+ erase(nested3),
+ erase(nested4),
+ erase(nested),
+ Self = self(),
+ Try =
+ try
+ try self()
+ after
+ After =
+ try
+ foo(X1)
+ of
+ V1 -> {value1,foo(X2)}
+ catch
+ C1:V1 -> {caught1,foo(X2)}
+ after
+ put(nested3, foo(X3))
+ end,
+ put(nested4, After)
+ end
+ of
+ Self -> value
+ catch
+ C:D -> {caught,{C,D}}
+ after
+ put(nested, finalized)
+ end,
+ {Try,erase(nested3),erase(nested4),erase(nested)}.
+
+foo({value,Value}) -> Value;
+foo({'div',{A,B}}) ->
+ my_div(A, B);
+foo({'add',{A,B}}) ->
+ my_add(A, B);
+foo({'abs',X}) ->
+ my_abs(X);
+foo({error,Error}) ->
+ erlang:error(Error);
+foo({throw,Throw}) ->
+ erlang:throw(Throw);
+foo({exit,Exit}) ->
+ erlang:exit(Exit);
+foo({raise,{Class,Reason}}) ->
+ erlang:raise(Class, Reason).
+%%foo(function_clause) -> % must not be defined!
+
+my_div(A, B) ->
+ A div B.
+
+my_add(A, B) ->
+ A + B.
+
+my_abs(X) -> abs(X).
+
+id(I) -> I.
diff --git a/lib/debugger/vsn.mk b/lib/debugger/vsn.mk
index f33d66b5cf..654dc11e20 100644
--- a/lib/debugger/vsn.mk
+++ b/lib/debugger/vsn.mk
@@ -1 +1 @@
-DEBUGGER_VSN = 3.2.3
+DEBUGGER_VSN = 3.2.4
diff --git a/lib/dialyzer/RELEASE_NOTES b/lib/dialyzer/RELEASE_NOTES
index 62b0c92f97..a05b3ac52b 100644
--- a/lib/dialyzer/RELEASE_NOTES
+++ b/lib/dialyzer/RELEASE_NOTES
@@ -3,8 +3,19 @@
(in reversed chronological order)
==============================================================================
-Version 2.3.0 (in Erlang/OTP R14)
----------------------------------
+Version 2.x.x (in Erlang/OTP R14B01)
+------------------------------------
+ - Fixed problems in the handling of remote types in records used as types
+ (thanks to Nico Kruber for the report and to Maria Christakis for the fix).
+ - Fixed handling of nested opaque types (thanks to Thorsten Schuett for
+ reporting it and to Maria Christakis for fixing it).
+
+Version 2.3.1 (in Erlang/OTP R14B)
+----------------------------------
+ - Eliminated warnings for auto-imported BIF clashes.
+
+Version 2.3.0 (in Erlang/OTP R14A)
+----------------------------------
- Dialyzer properly supports the new attribute -export_type and checks
that remote types only refer to exported types. A warning is produced
if some files/applications refer to types defined in modules which are
diff --git a/lib/dialyzer/doc/src/dialyzer.xml b/lib/dialyzer/doc/src/dialyzer.xml
index 1ec2ce830a..29308885fd 100644
--- a/lib/dialyzer/doc/src/dialyzer.xml
+++ b/lib/dialyzer/doc/src/dialyzer.xml
@@ -101,9 +101,9 @@
<tag><c><![CDATA[--output_plt file]]></c></tag>
<item>Store the PLT at the specified location after building it.</item>
<tag><c><![CDATA[--plt plt]]></c></tag>
- <item>Use the specified plt as the initial persistent lookup table.</item>
+ <item>Use the specified PLT as the initial persistent lookup table.</item>
<tag><c><![CDATA[-Wwarn]]></c></tag>
- <item>a family of option which selectively turn on/off warnings.
+ <item>a family of options which selectively turn on/off warnings.
(for help on the names of warnings use <c><![CDATA[dialyzer -Whelp]]></c>)</item>
<tag><c><![CDATA[--shell]]></c></tag>
<item>do not disable the Erlang shell while running the GUI</item>
@@ -158,9 +158,16 @@
<tag><c><![CDATA[-Wno_match]]></c></tag>
<item>Suppress warnings for patterns that are unused or cannot
match.</item>
+ <tag><c><![CDATA[-Wno_opaque]]></c></tag>
+ <item>Suppress warnings for violations of opaqueness of data types.</item>
<tag><c><![CDATA[-Werror_handling]]></c>***</tag>
<item>Include warnings for functions that only return by means of an
exception.</item>
+ <tag><c><![CDATA[-Wrace_conditions]]></c>***</tag>
+ <item>Include warnings for possible race conditions.</item>
+ <tag><c><![CDATA[-Wbehaviours]]></c>***</tag>
+ <item>Include warnings about behaviour callbacks which drift from the
+ published recommended interfaces.</item>
<tag><c><![CDATA[-Wunmatched_returns]]></c>***</tag>
<item>Include warnings for function calls which ignore a structured return
value or do not match against one of many possible return value(s).</item>
@@ -215,8 +222,11 @@ WarnOpts : no_return
| no_improper_lists
| no_fun_app
| no_match
+ | no_opaque
| no_fail_call
| error_handling
+ | race_conditions
+ | behaviours
| unmatched_returns
| overspecs
| underspecs
diff --git a/lib/dialyzer/doc/src/notes.xml b/lib/dialyzer/doc/src/notes.xml
index 856af01525..ac3857b9ef 100755
--- a/lib/dialyzer/doc/src/notes.xml
+++ b/lib/dialyzer/doc/src/notes.xml
@@ -31,6 +31,21 @@
<p>This document describes the changes made to the Dialyzer
application.</p>
+<section><title>Dialyzer 2.3.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Eliminated warnings for auto-imported BIF clashes.</p>
+ <p>
+ Own Id: OTP-8840</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Dialyzer 2.3.0</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/dialyzer/src/dialyzer_cl.erl b/lib/dialyzer/src/dialyzer_cl.erl
index 57f0d6e736..616e2465dc 100644
--- a/lib/dialyzer/src/dialyzer_cl.erl
+++ b/lib/dialyzer/src/dialyzer_cl.erl
@@ -29,6 +29,10 @@
-module(dialyzer_cl).
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
+%% Avoid warning for local function error/2 clashing with autoimported BIF.
+-compile({no_auto_import,[error/2]}).
-export([start/1]).
-include("dialyzer.hrl").
diff --git a/lib/dialyzer/src/dialyzer_cl_parse.erl b/lib/dialyzer/src/dialyzer_cl_parse.erl
index 9a522e906a..0160b84abc 100644
--- a/lib/dialyzer/src/dialyzer_cl_parse.erl
+++ b/lib/dialyzer/src/dialyzer_cl_parse.erl
@@ -20,6 +20,8 @@
-module(dialyzer_cl_parse).
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([start/0]).
-export([collect_args/1]). % used also by typer_options.erl
diff --git a/lib/dialyzer/src/dialyzer_plt.erl b/lib/dialyzer/src/dialyzer_plt.erl
index 268ec4a5f0..08d0b318b5 100644
--- a/lib/dialyzer/src/dialyzer_plt.erl
+++ b/lib/dialyzer/src/dialyzer_plt.erl
@@ -28,6 +28,8 @@
%%%-------------------------------------------------------------------
-module(dialyzer_plt).
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([check_plt/3,
compute_md5_from_files/1,
contains_mfa/2,
@@ -242,9 +244,10 @@ from_file(FileName, ReturnInfo) ->
[FileName, Reason]))
end.
--type inc_file_err_rsn() :: 'no_such_file' | 'read_error'.
+-type err_rsn() :: 'not_valid' | 'no_such_file' | 'read_error'.
+
-spec included_files(file:filename()) -> {'ok', [file:filename()]}
- | {'error', inc_file_err_rsn()}.
+ | {'error', err_rsn()}.
included_files(FileName) ->
case get_record_from_file(FileName) of
@@ -318,8 +321,7 @@ to_file(FileName,
end.
-type md5_diff() :: [{'differ', atom()} | {'removed', atom()}].
--type check_error() :: 'not_valid' | 'no_such_file' | 'read_error'
- | {'no_file_to_remove', file:filename()}.
+-type check_error() :: err_rsn() | {'no_file_to_remove', file:filename()}.
-spec check_plt(file:filename(), [file:filename()], [file:filename()]) ->
'ok'
diff --git a/lib/dialyzer/src/dialyzer_races.erl b/lib/dialyzer/src/dialyzer_races.erl
index ec8d613b96..ee9d5e88a3 100644
--- a/lib/dialyzer/src/dialyzer_races.erl
+++ b/lib/dialyzer/src/dialyzer_races.erl
@@ -118,7 +118,7 @@
var_map :: dict()}).
-type case_tags() :: 'beg_case' | #beg_clause{} | #end_clause{} | #end_case{}.
--type code() :: [#dep_call{} | #warn_call{} | #fun_call{} |
+-type code() :: [#dep_call{} | #fun_call{} | #warn_call{} |
#curr_fun{} | #let_tag{} | case_tags() | race_tag()].
-type table_var() :: label() | ?no_label.
@@ -479,23 +479,11 @@ fixup_race_forward(CurrFun, CurrFunLabel, Calls, Code, RaceList,
_Other ->
{RaceList, [], NestingLevel, false}
end;
- #dep_call{call_name = ets_lookup, args = DepCallArgs} ->
+ #dep_call{call_name = ets_lookup} ->
case RaceWarnTag of
?WARN_ETS_LOOKUP_INSERT ->
- [Tab, Names, _, _] = DepCallArgs,
- case compare_var_list(Tab,
- dialyzer_callgraph:get_public_tables(Callgraph),
- RaceVarMap)
- orelse
- length(Names --
- dialyzer_callgraph:get_named_tables(Callgraph)) <
- length(Names) of
- true ->
- {[Head#dep_call{var_map = RaceVarMap}|RaceList],
- [], NestingLevel, false};
- false ->
- {RaceList, [], NestingLevel, false}
- end;
+ {[Head#dep_call{var_map = RaceVarMap}|RaceList],
+ [], NestingLevel, false};
_Other ->
{RaceList, [], NestingLevel, false}
end;
@@ -517,23 +505,11 @@ fixup_race_forward(CurrFun, CurrFunLabel, Calls, Code, RaceList,
_Other ->
{RaceList, [], NestingLevel, false}
end;
- #warn_call{call_name = ets_insert, args = WarnCallArgs} ->
+ #warn_call{call_name = ets_insert} ->
case RaceWarnTag of
?WARN_ETS_LOOKUP_INSERT ->
- [Tab, Names, _, _] = WarnCallArgs,
- case compare_var_list(Tab,
- dialyzer_callgraph:get_public_tables(Callgraph),
- RaceVarMap)
- orelse
- length(Names --
- dialyzer_callgraph:get_named_tables(Callgraph)) <
- length(Names) of
- true ->
- {[Head#warn_call{var_map = RaceVarMap}|RaceList],
- [], NestingLevel, false};
- false ->
- {RaceList, [], NestingLevel, false}
- end;
+ {[Head#warn_call{var_map = RaceVarMap}|RaceList],
+ [], NestingLevel, false};
_Other ->
{RaceList, [], NestingLevel, false}
end;
diff --git a/lib/dialyzer/src/dialyzer_utils.erl b/lib/dialyzer/src/dialyzer_utils.erl
index a9da229061..248fdf6835 100644
--- a/lib/dialyzer/src/dialyzer_utils.erl
+++ b/lib/dialyzer/src/dialyzer_utils.erl
@@ -66,7 +66,7 @@ print_types1([{opaque, _Name} = Key|T], RecDict) ->
io:format("\n~w: ~w\n", [Key, erl_types:t_from_form(Form, RecDict)]),
print_types1(T, RecDict);
print_types1([{record, _Name} = Key|T], RecDict) ->
- {ok, [{Arity, Fields} = AF]} = dict:find(Key, RecDict),
+ {ok, [{_Arity, _Fields} = AF]} = dict:find(Key, RecDict),
io:format("~w: ~w\n\n", [Key, AF]),
print_types1(T, RecDict).
-define(debug(D_), print_types(D_)).
@@ -211,9 +211,9 @@ get_record_and_type_info([_Other|Left], Module, Records, RecDict) ->
get_record_and_type_info([], _Module, Records, RecDict) ->
case type_record_fields(lists:reverse(Records), RecDict) of
{ok, _NewRecDict} = Ok ->
- ?debug(NewRecDict),
+ ?debug(_NewRecDict),
Ok;
- {Name, {error, Error}} ->
+ {error, Name, Error} ->
{error, lists:flatten(io_lib:format(" Error while parsing #~w{}: ~s\n",
[Name, Error]))}
end.
@@ -269,9 +269,9 @@ type_record_fields([RecKey|Recs], RecDict) ->
RecDict2 = dict:update(RecKey, Fun, RecDict1),
type_record_fields(Recs, RecDict2)
catch
- throw:{error, _} = Error ->
+ throw:{error, Error} ->
{record, Name} = RecKey,
- {Name, Error}
+ {error, Name, Error}
end.
-spec process_record_remote_types(dialyzer_codeserver:codeserver()) -> dialyzer_codeserver:codeserver().
@@ -378,7 +378,7 @@ sets_filter([Mod|Mods], ExpTypes) ->
-spec src_compiler_opts() -> [compile:option(),...].
src_compiler_opts() ->
- [no_copt, to_core, binary, return_errors,
+ [no_copt, to_core, binary, return_errors,
no_inline, strict_record_tests, strict_record_updates,
no_is_record_optimization].
diff --git a/lib/dialyzer/vsn.mk b/lib/dialyzer/vsn.mk
index f2daf86def..d3574e0a71 100644
--- a/lib/dialyzer/vsn.mk
+++ b/lib/dialyzer/vsn.mk
@@ -1 +1 @@
-DIALYZER_VSN = 2.3.0
+DIALYZER_VSN = 2.3.1
diff --git a/lib/docbuilder/doc/src/notes.xml b/lib/docbuilder/doc/src/notes.xml
index 725aae0a68..019cf1b083 100644
--- a/lib/docbuilder/doc/src/notes.xml
+++ b/lib/docbuilder/doc/src/notes.xml
@@ -31,6 +31,22 @@
<p>This document describes the changes made to the DocBuilder
application.</p>
+<section><title>Docbuilder 0.9.8.8</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fixed problem with a centered table that was
+ transformed into an xml document which then produced
+ mis-formatted html. </p>
+ <p>
+ Own Id: OTP-8784</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Docbuilder 0.9.8.7</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/docbuilder/src/docb_edoc_xml_cb.erl b/lib/docbuilder/src/docb_edoc_xml_cb.erl
index f5cfc0fe18..90491bc007 100644
--- a/lib/docbuilder/src/docb_edoc_xml_cb.erl
+++ b/lib/docbuilder/src/docb_edoc_xml_cb.erl
@@ -340,9 +340,7 @@ otp_xmlify_e(#xmlElement{name=code} = E) -> % 4)
[E#xmlElement{content=Content}]
end;
otp_xmlify_e(#xmlElement{name=Tag} = E) % 5a
- when Tag==h1; Tag==h2; Tag==h3; Tag==h4; Tag==h5;
- Tag==center;
- Tag==font ->
+ when Tag==h1; Tag==h2; Tag==h3; Tag==h4; Tag==h5 ->
Content = text_only(E#xmlElement.content),
[E#xmlElement{name=b, content=Content}];
otp_xmlify_e(#xmlElement{name=Tag} = E) % 5b-c)
@@ -354,21 +352,16 @@ otp_xmlify_e(#xmlElement{name=table} = E) -> % 6)
module ->
otp_xmlify_table(E#xmlElement.content);
overview ->
- case get_attrval(border, E) of
- "" -> % implies border="0"
- [{p, otp_xmlify_table(E#xmlElement.content)}];
- "0" ->
- [{p, otp_xmlify_table(E#xmlElement.content)}];
- _Val ->
- Content0 = otp_xmlify_e(E#xmlElement.content),
- Summary = #xmlText{value=get_attrval(summary, E)},
- TCaption = E#xmlElement{name=tcaption,
- attributes=[],
- content=[Summary]},
- Content = Content0 ++ [TCaption],
- [E#xmlElement{attributes=[], content=Content}]
- end
+ Content0 = otp_xmlify_e(E#xmlElement.content),
+ Summary = #xmlText{value=get_attrval(summary, E)},
+ TCaption = E#xmlElement{name=tcaption,
+ attributes=[],
+ content=[Summary]},
+ Content = Content0 ++ [TCaption],
+ [E#xmlElement{attributes=[], content=Content}]
end;
+otp_xmlify_e(#xmlElement{name=tbody} = E) ->
+ otp_xmlify_e(E#xmlElement.content);
otp_xmlify_e(#xmlElement{name=sup} = E) -> % 7)
Text = get_text(E),
[#xmlText{parents = E#xmlElement.parents,
diff --git a/lib/docbuilder/vsn.mk b/lib/docbuilder/vsn.mk
index 2852ebcc8b..b23ee521c7 100644
--- a/lib/docbuilder/vsn.mk
+++ b/lib/docbuilder/vsn.mk
@@ -1,14 +1 @@
-DOCB_VSN = 0.9.8.7
-
-TICKETS = OTP-8343
-
-TICKETS_0.9.8.6 = OTP-8201
-
-TICKETS_0.9.8.5 = OTP-7851
-
-TICKETS_0.9.8.4 = OTP-7236
-
-TICKETS_0.9.8.1 = OTP-7236
-
-
-
+DOCB_VSN = 0.9.8.8
diff --git a/lib/edoc/doc/src/notes.xml b/lib/edoc/doc/src/notes.xml
index 74fa2d3ab6..83ad27ed31 100644
--- a/lib/edoc/doc/src/notes.xml
+++ b/lib/edoc/doc/src/notes.xml
@@ -31,6 +31,21 @@
<p>This document describes the changes made to the EDoc
application.</p>
+<section><title>Edoc 0.7.6.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Edoc now uses the new API functions to <c>inets</c>
+ instead of the deprecated ones.</p>
+ <p>
+ Own Id: OTP-8749</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Edoc 0.7.6.6</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/edoc/src/edoc.erl b/lib/edoc/src/edoc.erl
index ec452a5929..75b3bb451a 100644
--- a/lib/edoc/src/edoc.erl
+++ b/lib/edoc/src/edoc.erl
@@ -58,6 +58,8 @@
read_comments/1, read_comments/2,
read_source/1, read_source/2]).
+-compile({no_auto_import,[error/1]}).
+
-import(edoc_report, [report/2, report/3, error/1, error/3]).
-include("edoc.hrl").
diff --git a/lib/edoc/src/edoc_report.erl b/lib/edoc/src/edoc_report.erl
index b87c58dde3..ee54c60c90 100644
--- a/lib/edoc/src/edoc_report.erl
+++ b/lib/edoc/src/edoc_report.erl
@@ -27,6 +27,8 @@
-module(edoc_report).
+%% Avoid warning for local function error/2 clashing with autoimported BIF.
+-compile({no_auto_import,[error/2]}).
-export([error/1,
error/2,
error/3,
diff --git a/lib/edoc/src/edoc_run.erl b/lib/edoc/src/edoc_run.erl
index 37025d6621..96e5ea4631 100644
--- a/lib/edoc/src/edoc_run.erl
+++ b/lib/edoc/src/edoc_run.erl
@@ -42,6 +42,8 @@
-export([file/1, application/1, packages/1, files/1, toc/1]).
+-compile({no_auto_import,[error/1]}).
+
-import(edoc_report, [report/2, error/1]).
diff --git a/lib/edoc/vsn.mk b/lib/edoc/vsn.mk
index 2de2641b4a..75e9a5c971 100644
--- a/lib/edoc/vsn.mk
+++ b/lib/edoc/vsn.mk
@@ -1 +1 @@
-EDOC_VSN = 0.7.6.6
+EDOC_VSN = 0.7.6.7
diff --git a/lib/erl_docgen/doc/src/notes.xml b/lib/erl_docgen/doc/src/notes.xml
index ce6ba3d923..5b5398fec6 100644
--- a/lib/erl_docgen/doc/src/notes.xml
+++ b/lib/erl_docgen/doc/src/notes.xml
@@ -29,7 +29,22 @@
<file>notes.xml</file>
</header>
<p>This document describes the changes made to the erl_docgen application.</p>
- <section><title>erl_docgen 0.2.1</title>
+ <section><title>Erl_Docgen 0.2.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fixed the transformation from xml to html of the
+ funcs block in comref pages. </p>
+ <p>
+ Own Id: OTP-8792</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>erl_docgen 0.2.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/erl_docgen/priv/xsl/db_html.xsl b/lib/erl_docgen/priv/xsl/db_html.xsl
index 5614b02bb7..bba0f97645 100644
--- a/lib/erl_docgen/priv/xsl/db_html.xsl
+++ b/lib/erl_docgen/priv/xsl/db_html.xsl
@@ -1157,6 +1157,7 @@
</xsl:template>
+
<xsl:template match="name">
<xsl:variable name="tmpstring">
@@ -1208,6 +1209,9 @@
</xsl:variable>
<a name="{$fname}-{$arity}"><span class="bold_code"><xsl:value-of select="."/></span></a><br/>
</xsl:when>
+ <xsl:otherwise>
+ <span class="bold_code"><xsl:value-of select="."/></span>
+ </xsl:otherwise>
</xsl:choose>
</xsl:template>
diff --git a/lib/erl_docgen/vsn.mk b/lib/erl_docgen/vsn.mk
index 5b14051034..0bc01f7d49 100644
--- a/lib/erl_docgen/vsn.mk
+++ b/lib/erl_docgen/vsn.mk
@@ -1,22 +1 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2009-2010. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-#
-
-ERL_DOCGEN_VSN = 0.2.1
-
-TICKETS =
+ERL_DOCGEN_VSN = 0.2.2
diff --git a/lib/erl_interface/configure.in b/lib/erl_interface/configure.in
index 7728cb97be..72ac8c7bbf 100644
--- a/lib/erl_interface/configure.in
+++ b/lib/erl_interface/configure.in
@@ -288,13 +288,7 @@ case "$threads_disabled" in
;;
win32_threads)
EI_THREADS="true"
- AC_MSG_CHECKING([for __declspec(thread) usability])
- if test "X$GCC" = "Xyes"; then
- AC_MSG_RESULT([no])
- else
- THR_DEFS="$THR_DEFS -DUSE_DECLSPEC_THREAD"
- AC_MSG_RESULT([yes])
- fi
+ THR_DEFS="$THR_DEFS -D_WIN32_WINNT=0x0500 -DWINVER=0x0500"
;;
pthread)
EI_THREADS="true"
diff --git a/lib/erl_interface/doc/src/ei_connect.xml b/lib/erl_interface/doc/src/ei_connect.xml
index 927395d1bf..f562615ddd 100644
--- a/lib/erl_interface/doc/src/ei_connect.xml
+++ b/lib/erl_interface/doc/src/ei_connect.xml
@@ -4,7 +4,7 @@
<cref>
<header>
<copyright>
- <year>2001</year><year>2009</year>
+ <year>2001</year><year>2010</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -116,7 +116,7 @@
int n = 0;
struct in_addr addr;
ei_cnode ec;
-addr = inet_addr("150.236.14.75");
+addr.s_addr = inet_addr("150.236.14.75");
if (ei_connect_xinit(&ec,
"chivas",
"madonna",
@@ -132,7 +132,7 @@ if (ei_connect_xinit(&ec,
</p>
<code type="none"><![CDATA[
if (ei_connect_init(&ec, "madonna", "cookie...", n++) < 0) {
- fprintf("ERROR when initializing: %d",erl_errno);
+ fprintf(stderr,"ERROR when initializing: %d",erl_errno);
exit(-1);
}
]]></code>
@@ -177,7 +177,7 @@ int fd = ei_connect(&ec, NODE);
/*** Variant 2 ***/
struct in_addr addr;
-addr = inet_addr(IP_ADDR);
+addr.s_addr = inet_addr(IP_ADDR);
fd = ei_xconnect(&ec, &addr, ALIVE);
]]></code>
</desc>
@@ -508,7 +508,7 @@ if (ei_decode_version(result.buff, &index) < 0
same as the port number that was previously bound to the socket.</p>
<p><c><![CDATA[addr]]></c> is the 32-bit IP address of the local host.</p>
<p>To unregister with epmd, simply close the returned
- descriptor. See also <c><![CDATA[ei_unpublish()]]></c>.</p>
+ descriptor. Do not use <c><![CDATA[ei_unpublish()]]></c>, which is deprecated anyway.</p>
<p>On success, the functions return a descriptor connecting the
calling process to epmd. On failure, they return -1 and set
<c><![CDATA[erl_errno]]></c> to <c><![CDATA[EIO]]></c>.</p>
@@ -558,18 +558,21 @@ typedef struct {
</func>
<func>
<name><ret>int</ret><nametext>ei_unpublish(ei_cnode *ec)</nametext></name>
- <fsummary>Unpublish a node name</fsummary>
+ <fsummary>Forcefully unpublish a node name</fsummary>
<desc>
<p>This function can be called by a process to unregister a
- specified node from epmd on the localhost. This may be
- useful, for example, when epmd has not detected the failure of a
- node, and will not allow the name to be reused. If you use this
- function to unregister your own process, be sure to also close
- the descriptor that was returned by <c><![CDATA[ei_publish()]]></c>.</p>
- <note>
- <p>Careless use of this function may have unpredictable
- results, if the registered node is in fact still running.</p>
- </note>
+ specified node from epmd on the localhost. This is however usually not
+ allowed, unless epmd was started with the -relaxed_command_check
+ flag, which it normally isn't.</p>
+
+ <p>To unregister a node you have published, you should
+ close the descriptor that was returned by
+ <c><![CDATA[ei_publish()]]></c>.</p>
+
+ <warning>
+ <p>This function is deprecated and will be removed in a future
+ release.</p>
+ </warning>
<p><c><![CDATA[ec]]></c> is the node structure of the node to unregister.</p>
<p>If the node was successfully unregistered from epmd, the
function returns 0. Otherwise, it returns -1 and sets
diff --git a/lib/erl_interface/doc/src/erl_connect.xml b/lib/erl_interface/doc/src/erl_connect.xml
index b2235925b2..bd5e637244 100644
--- a/lib/erl_interface/doc/src/erl_connect.xml
+++ b/lib/erl_interface/doc/src/erl_connect.xml
@@ -4,7 +4,7 @@
<cref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2010</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -451,7 +451,7 @@ typedef struct {
<p><c><![CDATA[port]]></c> is the local name to register, and should be the
same as the port number that was previously bound to the socket.</p>
<p>To unregister with epmd, simply close the returned
- descriptor. See also <c><![CDATA[erl_unpublish()]]></c>.
+ descriptor.
</p>
<p>On success, the functions return a descriptor connecting the
calling process to epmd. On failure, they return -1 and set
@@ -507,21 +507,24 @@ typedef struct {
</func>
<func>
<name><ret>int</ret><nametext>erl_unpublish(alive)</nametext></name>
- <fsummary>Unpublish a node name</fsummary>
+ <fsummary>Forcefully unpublish a node name</fsummary>
<type>
<v>char *alive;</v>
</type>
<desc>
- <p>This function can be called by a process to unregister a
- specified node name from epmd on the localhost. This may be
- useful, for example, when epmd has not detected the failure of a
- node, and will not allow the name to be reused. If you use this
- function to unregister your own process, be sure to also close
- the descriptor that was returned by <c><![CDATA[erl_publish()]]></c>.</p>
- <note>
- <p>Careless use of this function may have unpredictable
- results, if the registered node is in fact still running.</p>
- </note>
+ <p>This function can be called by a process to unregister a
+ specified node from epmd on the localhost. This is however usually not
+ allowed, unless epmd was started with the -relaxed_command_check
+ flag, which it normally isn't.</p>
+
+ <p>To unregister a node you have published, you should instead
+ close the descriptor that was returned by
+ <c><![CDATA[ei_publish()]]></c>.</p>
+
+ <warning>
+ <p>This function is deprecated and will be removed in a future
+ release.</p>
+ </warning>
<p><c><![CDATA[alive]]></c> is the name of the node to unregister, i.e., the
first component of the nodename, without the <c><![CDATA[@hostname]]></c>.</p>
<p>If the node was successfully unregistered from epmd, the
diff --git a/lib/erl_interface/doc/src/notes.xml b/lib/erl_interface/doc/src/notes.xml
index 848da9cb23..ff89802599 100644
--- a/lib/erl_interface/doc/src/notes.xml
+++ b/lib/erl_interface/doc/src/notes.xml
@@ -30,6 +30,74 @@
</header>
<p>This document describes the changes made to the Erl_interface application.</p>
+<section><title>Erl_Interface 3.7.1.1</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The <c>erl_interface</c> tracelevel for erlang messages was incorrect. This has now been fixed.
+ </p>
+ <p>
+ Own Id: OTP-8874</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+<section><title>Erl_Interface 3.7.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Removed unused variable in <c>ei_decode_term.c</c>.</p>
+ <p>
+ Fixed faulty deallocation in <c>erl_call</c>.</p>
+ <p>
+ Own Id: OTP-8748</p>
+ </item>
+ <item>
+ <p>ei_connect: correct man page examples (Thanks to
+ Michael Santos)</p>
+ <p>
+ Own Id: OTP-8813</p>
+ </item>
+ <item>
+ <p>ei: prevent overflow in <c>ei_connect_init</c> and
+ <c>ei_xconnect</c></p> <p>Add length check of the buffer
+ before copying. (Thanks to Michael Santos)</p>
+ <p>
+ Own Id: OTP-8814</p>
+ </item>
+ <item>
+ <p>Remove DECLSPEC feature which fails on Windows Vista
+ and use the fallback implementation instead.</p>
+ <p>
+ Own Id: OTP-8826</p>
+ </item>
+ <item>
+ <p>erl_call: fix multiple buffer overflows (Thanks to
+ Michael Santos)</p>
+ <p>
+ Own Id: OTP-8827</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Fix incorrect writev iovec buffer handling in
+ <c>erl_interface</c> (Thanks to Steve Vinoski)</p>
+ <p>
+ Own Id: OTP-8837</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erl_Interface 3.7</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/erl_interface/src/connect/ei_connect.c b/lib/erl_interface/src/connect/ei_connect.c
index b1b79aa0e5..99ccba0686 100644
--- a/lib/erl_interface/src/connect/ei_connect.c
+++ b/lib/erl_interface/src/connect/ei_connect.c
@@ -366,16 +366,16 @@ static int initWinSock(void)
WORD wVersionRequested;
WSADATA wsaData;
int i;
- /* FIXME problem for threaded ? */
- static int initialized = 0;
+
+ static LONG volatile initialized = 0;
wVersionRequested = MAKEWORD(1, 1);
- if (!initialized) {
- initialized = 1;
+ if (InterlockedCompareExchange((LPLONG) &initialized,1L,0L) == 0L) {
/* FIXME not terminate, just a message?! */
if ((i = WSAStartup(wVersionRequested, &wsaData))) {
EI_TRACE_ERR1("ei_connect_init",
"ERROR: can't initialize windows sockets: %d",i);
+ initialized = 2L;
return 0;
}
@@ -383,10 +383,14 @@ static int initWinSock(void)
EI_TRACE_ERR0("initWinSock","ERROR: this version of windows "
"sockets not supported");
WSACleanup();
+ initialized = 2L;
return 0;
}
+ initialized = 3L;
+ } else while (initialized < 2) {
+ SwitchToThread();
}
- return 1;
+ return (int) (initialized - 2);
}
#endif
@@ -502,10 +506,14 @@ int ei_connect_init(ei_cnode* ec, const char* this_node_name,
return ERL_ERROR;
}
- if (this_node_name == NULL)
+ if (this_node_name == NULL) {
sprintf(thisalivename, "c%d", (int) getpid());
- else
+ } else if (strlen(this_node_name) >= sizeof(thisalivename)) {
+ EI_TRACE_ERR0("ei_connect_init","ERROR: this_node_name too long");
+ return ERL_ERROR;
+ } else {
strcpy(thisalivename, this_node_name);
+ }
if ((hp = ei_gethostbyname(thishostname)) == 0) {
/* Looking up IP given hostname fails. We must be on a standalone
diff --git a/lib/erl_interface/src/connect/ei_resolve.c b/lib/erl_interface/src/connect/ei_resolve.c
index 42aeab22b1..24a030c468 100644
--- a/lib/erl_interface/src/connect/ei_resolve.c
+++ b/lib/erl_interface/src/connect/ei_resolve.c
@@ -601,7 +601,7 @@ struct hostent *ei_gethostbyaddr_r(const char *addr,
#ifndef HAVE_GETHOSTBYNAME_R
return my_gethostbyaddr_r(addr,length,type,hostp,buffer,buflen,h_errnop);
#else
-#if (defined(__GLIBC__) || (__FreeBSD_version >= 602000))
+#if (defined(__GLIBC__) || (__FreeBSD_version >= 602000) || defined(__DragonFly__))
struct hostent *result;
gethostbyaddr_r(addr, length, type, hostp, buffer, buflen, &result,
@@ -628,7 +628,7 @@ struct hostent *ei_gethostbyname_r(const char *name,
#ifndef HAVE_GETHOSTBYNAME_R
return my_gethostbyname_r(name,hostp,buffer,buflen,h_errnop);
#else
-#if (defined(__GLIBC__) || (__FreeBSD_version >= 602000))
+#if (defined(__GLIBC__) || (__FreeBSD_version >= 602000) || defined(__DragonFly__))
struct hostent *result;
gethostbyname_r(name, hostp, buffer, buflen, &result, h_errnop);
diff --git a/lib/erl_interface/src/connect/eirecv.c b/lib/erl_interface/src/connect/eirecv.c
index 51fc32d65c..7d72ddeeae 100644
--- a/lib/erl_interface/src/connect/eirecv.c
+++ b/lib/erl_interface/src/connect/eirecv.c
@@ -107,7 +107,7 @@ ei_recv_internal (int fd,
switch (msg->msgtype) {
case ERL_SEND: /* { SEND, Cookie, ToPid } */
- if (ei_tracelevel > 0) show_this_msg = 1;
+ if (ei_tracelevel >= 4) show_this_msg = 1;
if (ei_decode_atom(header,&index,msg->cookie)
|| ei_decode_pid(header,&index,&msg->to))
{
@@ -118,7 +118,7 @@ ei_recv_internal (int fd,
break;
case ERL_REG_SEND: /* { REG_SEND, From, Cookie, ToName } */
- if (ei_tracelevel > 0) show_this_msg = 1;
+ if (ei_tracelevel >= 4) show_this_msg = 1;
if (ei_decode_pid(header,&index,&msg->from)
|| ei_decode_atom(header,&index,msg->cookie)
|| ei_decode_atom(header,&index,msg->toname))
@@ -133,7 +133,7 @@ ei_recv_internal (int fd,
case ERL_LINK: /* { LINK, From, To } */
case ERL_UNLINK: /* { UNLINK, From, To } */
case ERL_GROUP_LEADER: /* { GROUP_LEADER, From, To } */
- if (ei_tracelevel > 1) show_this_msg = 1;
+ if (ei_tracelevel >= 4) show_this_msg = 1;
if (ei_decode_pid(header,&index,&msg->from)
|| ei_decode_pid(header,&index,&msg->to))
{
@@ -145,7 +145,7 @@ ei_recv_internal (int fd,
case ERL_EXIT: /* { EXIT, From, To, Reason } */
case ERL_EXIT2: /* { EXIT2, From, To, Reason } */
- if (ei_tracelevel > 1) show_this_msg = 1;
+ if (ei_tracelevel >= 4) show_this_msg = 1;
if (ei_decode_pid(header,&index,&msg->from)
|| ei_decode_pid(header,&index,&msg->to))
{
@@ -156,7 +156,7 @@ ei_recv_internal (int fd,
break;
case ERL_SEND_TT: /* { SEND_TT, Cookie, ToPid, TraceToken } */
- if (ei_tracelevel > 0) show_this_msg = 1;
+ if (ei_tracelevel >= 4) show_this_msg = 1;
if (ei_decode_atom(header,&index,msg->cookie)
|| ei_decode_pid(header,&index,&msg->to)
|| ei_decode_trace(header,&index,&msg->token))
@@ -169,7 +169,7 @@ ei_recv_internal (int fd,
break;
case ERL_REG_SEND_TT: /* { REG_SEND_TT, From, Cookie, ToName, TraceToken } */
- if (ei_tracelevel > 0) show_this_msg = 1;
+ if (ei_tracelevel >= 4) show_this_msg = 1;
if (ei_decode_pid(header,&index,&msg->from)
|| ei_decode_atom(header,&index,msg->cookie)
|| ei_decode_atom(header,&index,msg->toname)
@@ -184,7 +184,7 @@ ei_recv_internal (int fd,
case ERL_EXIT_TT: /* { EXIT_TT, From, To, TraceToken, Reason } */
case ERL_EXIT2_TT: /* { EXIT2_TT, From, To, TraceToken, Reason } */
- if (ei_tracelevel > 1) show_this_msg = 1;
+ if (ei_tracelevel >= 4) show_this_msg = 1;
if (ei_decode_pid(header,&index,&msg->from)
|| ei_decode_pid(header,&index,&msg->to)
|| ei_decode_trace(header,&index,&msg->token))
@@ -197,7 +197,7 @@ ei_recv_internal (int fd,
break;
case ERL_NODE_LINK: /* { NODE_LINK } */
- if (ei_tracelevel > 1) show_this_msg = 1;
+ if (ei_tracelevel >= 4) show_this_msg = 1;
break;
default:
diff --git a/lib/erl_interface/src/connect/send.c b/lib/erl_interface/src/connect/send.c
index cd832db4ea..57e32903cf 100644
--- a/lib/erl_interface/src/connect/send.c
+++ b/lib/erl_interface/src/connect/send.c
@@ -87,8 +87,7 @@ int ei_send_encoded_tmo(int fd, const erlang_pid *to,
put8(s, ERL_PASS_THROUGH); /* 1 */
/*** sum: 1070 */
- /* FIXME incorrect level */
- if (ei_tracelevel > 0)
+ if (ei_tracelevel >= 4)
ei_show_sendmsg(stderr,header,msg);
#ifdef HAVE_WRITEV
diff --git a/lib/erl_interface/src/connect/send_exit.c b/lib/erl_interface/src/connect/send_exit.c
index 098797c96d..d4e6605a2c 100644
--- a/lib/erl_interface/src/connect/send_exit.c
+++ b/lib/erl_interface/src/connect/send_exit.c
@@ -88,8 +88,7 @@ int ei_send_exit_tmo(int fd, const erlang_pid *from, const erlang_pid *to,
put32be(s, index - 4); /* 4 */
put8(s, ERL_PASS_THROUGH); /* 1 */
/*** sum: len + 1080 */
- /* FIXME incorrect level */
- if (ei_tracelevel > 1)
+ if (ei_tracelevel >= 4)
ei_show_sendmsg(stderr,msgbuf,NULL);
ei_write_fill_t(fd,msgbuf,index,ms);
diff --git a/lib/erl_interface/src/connect/send_reg.c b/lib/erl_interface/src/connect/send_reg.c
index 8f0e40309c..779b1b8359 100644
--- a/lib/erl_interface/src/connect/send_reg.c
+++ b/lib/erl_interface/src/connect/send_reg.c
@@ -82,8 +82,7 @@ int ei_send_reg_encoded_tmo(int fd, const erlang_pid *from,
put32be(s, index + msglen - 4); /* 4 */
put8(s, ERL_PASS_THROUGH); /* 1 */
/*** sum: 1336 */
- /* FIXME incorrect level.... */
- if (ei_tracelevel > 0)
+ if (ei_tracelevel >= 4)
ei_show_sendmsg(stderr,header,msg);
#ifdef HAVE_WRITEV
diff --git a/lib/erl_interface/src/epmd/ei_epmd.h b/lib/erl_interface/src/epmd/ei_epmd.h
index 40e5ece572..ccacfed244 100644
--- a/lib/erl_interface/src/epmd/ei_epmd.h
+++ b/lib/erl_interface/src/epmd/ei_epmd.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2010. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -40,20 +40,13 @@
#define EI_MYPROTO 0 /* tcp/ip */
#endif
-/* epmd r3 protocol */
-#ifndef EI_EPMD_ALIVE_REQ
-#define EI_EPMD_ALIVE_REQ 'a'
-#define EI_EPMD_ALIVE_OK_RESP 'Y'
-#define EI_EPMD_PORT_REQ 'p'
-#define EI_EPMD_STOP_REQ 's'
-#endif
-
/* epmd r4 */
#ifndef EI_EPMD_ALIVE2_REQ
#define EI_EPMD_ALIVE2_REQ 120
#define EI_EPMD_ALIVE2_RESP 121
#define EI_EPMD_PORT2_REQ 122
#define EI_EPMD_PORT2_RESP 119
+#define EI_EPMD_STOP_REQ 's'
#endif
/* internal functions */
diff --git a/lib/erl_interface/src/epmd/epmd_port.c b/lib/erl_interface/src/epmd/epmd_port.c
index 663b38d2d4..698c75c217 100644
--- a/lib/erl_interface/src/epmd/epmd_port.c
+++ b/lib/erl_interface/src/epmd/epmd_port.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2010. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -92,64 +92,6 @@ int ei_epmd_connect_tmo(struct in_addr *inaddr, unsigned ms)
return sd;
}
-/* get the given node's listen port using old epmd protocol */
-static int ei_epmd_r3_port (struct in_addr *addr, const char *alive,
- unsigned ms)
-{
- char buf[EPMDBUF];
- char *s = buf;
- int len = strlen(alive) + 1;
- int fd;
- int port;
- int res;
-#if defined(VXWORKS)
- char ntoabuf[32];
-#endif
-
- put16be(s,len);
- put8(s,EI_EPMD_PORT_REQ);
- strcpy(s,alive);
-
- /* connect to epmd */
- if ((fd = ei_epmd_connect_tmo(addr,ms)) < 0)
- {
- /* ei_epmd_connect_tmo() sets erl_errno */
- return -1;
- }
-
- if ((res = ei_write_fill_t(fd, buf, len+2, ms)) != len+2) {
- closesocket(fd);
- erl_errno = (res == -2) ? ETIMEDOUT : EIO;
- return -1;
- }
-
-#ifdef VXWORKS
- /* FIXME use union/macro for level. Correct level? */
- if (ei_tracelevel > 2) {
- inet_ntoa_b(*addr,ntoabuf);
- EI_TRACE_CONN2("ei_epmd_r3_port",
- "-> PORT_REQ alive=%s ip=%s",alive,ntoabuf);
- }
-#else
- EI_TRACE_CONN2("ei_epmd_r3_port",
- "-> PORT_REQ alive=%s ip=%s",alive,inet_ntoa(*addr));
-#endif
-
- if ((res = ei_read_fill_t(fd, buf, 2, ms)) != 2) {
- EI_TRACE_ERR0("ei_epmd_r3_port","<- CLOSE");
- closesocket(fd);
- erl_errno = (res == -2) ? ETIMEDOUT : EIO;
- return -1;
- }
- closesocket(fd);
- s = buf;
- port = get16be(s);
-
- EI_TRACE_CONN1("ei_epmd_r3_port","<- PORT_RESP port=%d",port);
-
- return port;
-}
-
static int ei_epmd_r4_port (struct in_addr *addr, const char *alive,
int *dist, unsigned ms)
{
@@ -164,6 +106,12 @@ static int ei_epmd_r4_port (struct in_addr *addr, const char *alive,
#if defined(VXWORKS)
char ntoabuf[32];
#endif
+
+ if (len > sizeof(buf) - 3)
+ {
+ erl_errno = ERANGE;
+ return -1;
+ }
put16be(s,len);
put8(s,EI_EPMD_PORT2_REQ);
@@ -285,15 +233,6 @@ int ei_epmd_port_tmo (struct in_addr *addr, const char *alive, int *dist,
{
int i;
- /* try the new one first, then the old one */
- i = ei_epmd_r4_port(addr,alive,dist,ms);
-
- /* -2: new protocol not understood */
- if (i == -2) {
- *dist = 0;
- i = ei_epmd_r3_port(addr,alive,ms);
- }
-
- return i;
+ return ei_epmd_r4_port(addr,alive,dist,ms);
}
diff --git a/lib/erl_interface/src/epmd/epmd_publish.c b/lib/erl_interface/src/epmd/epmd_publish.c
index 09b3dce43b..a9b8727747 100644
--- a/lib/erl_interface/src/epmd/epmd_publish.c
+++ b/lib/erl_interface/src/epmd/epmd_publish.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2010. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -55,62 +55,6 @@
/* publish our listen port and alive name */
/* return the (useless) creation number */
-static int ei_epmd_r3_publish (int port, const char *alive, unsigned ms)
-{
- char buf[EPMDBUF];
- char *s = buf;
- int fd;
- int len = strlen(alive) + 3;
- int res,creation;
-
- s = buf;
- put16be(s,len);
- put8(s,EI_EPMD_ALIVE_REQ);
- put16be(s,port);
- strcpy(s, alive);
-
- if ((fd = ei_epmd_connect_tmo(NULL,ms)) < 0) return fd;
-
- if ((res = ei_write_fill_t(fd, buf, len+2, ms)) != len+2) {
- closesocket(fd);
- erl_errno = (res == -2) ? ETIMEDOUT : EIO;
- return -1;
- }
-
- EI_TRACE_CONN2("ei_epmd_r3_publish",
- "-> ALIVE_REQ alive=%s port=%d",alive,port);
-
- if ((res = ei_read_fill_t(fd, buf, 3, ms)) != 3) {
- closesocket(fd);
- erl_errno = (res == -2) ? ETIMEDOUT : EIO;
- return -1;
- }
-
- s = buf;
- if ((res=get8(s)) != EI_EPMD_ALIVE_OK_RESP) {
- EI_TRACE_ERR1("ei_epmd_r3_publish",
- "<- ALIVE_NOK result=%d (failure)",res);
- closesocket(fd);
- erl_errno = EIO;
- return -1;
- }
-
- creation = get16be(s);
-
- EI_TRACE_CONN1("ei_epmd_r3_publish","<- ALIVE_OK creation=%d",creation);
-
- /* Don't close fd here! It keeps us registered with epmd */
-
- /* probably should save fd so we can close it later... */
- /* epmd_saveconn(OPEN,fd,alive); */
-
- /* return the creation number, for no good reason */
- /* return creation; */
-
- /* no! return the descriptor */
- return fd;
-}
-
/* publish our listen port and alive name */
/* return the (useless) creation number */
/* this protocol is a lot more complex than the old one */
@@ -200,15 +144,7 @@ int ei_epmd_publish(int port, const char *alive)
int ei_epmd_publish_tmo(int port, const char *alive, unsigned ms)
{
- int i;
-
- /* try the new one first, then the old one */
- i = ei_epmd_r4_publish(port,alive, ms);
-
- /* -2: new protocol not understood */
- if (i == -2) i = ei_epmd_r3_publish(port,alive, ms);
-
- return i;
+ return ei_epmd_r4_publish(port,alive, ms);;
}
diff --git a/lib/erl_interface/src/misc/ei_format.c b/lib/erl_interface/src/misc/ei_format.c
index 08235d0ebe..b35421d4b2 100644
--- a/lib/erl_interface/src/misc/ei_format.c
+++ b/lib/erl_interface/src/misc/ei_format.c
@@ -106,6 +106,8 @@ static int eiformat(const char** fmt, union arg** args, ei_x_buff* x)
default:
if (isdigit((int)*p))
res = pdigit(&p, x);
+ else if ((*p == '-' || *p == '+') && isdigit((int)*(p+1)))
+ res = pdigit(&p, x);
else if (islower((int)*p))
res = patom(&p, x);
else
@@ -149,6 +151,8 @@ static int pdigit(const char** fmt, ei_x_buff* x)
double d;
long l;
+ if (**fmt == '-' || **fmt == '+')
+ (*fmt)++;
for (;;) {
c = *(*fmt)++;
if (isdigit((int)c))
diff --git a/lib/erl_interface/src/misc/ei_portio.c b/lib/erl_interface/src/misc/ei_portio.c
index b73ebebbe1..c4e397f1e0 100644
--- a/lib/erl_interface/src/misc/ei_portio.c
+++ b/lib/erl_interface/src/misc/ei_portio.c
@@ -171,6 +171,8 @@ int ei_writev_fill_t(int fd, const struct iovec *iov, int iovcnt, unsigned
}
while (i > 0) {
if (i < current_iov[0].iov_len) {
+ char *p = (char*)current_iov[0].iov_base;
+ current_iov[0].iov_base = p + i;
current_iov[0].iov_len -= i;
i = 0;
} else {
diff --git a/lib/erl_interface/src/prog/erl_call.c b/lib/erl_interface/src/prog/erl_call.c
index 93b84cbb36..33ff6da7c9 100644
--- a/lib/erl_interface/src/prog/erl_call.c
+++ b/lib/erl_interface/src/prog/erl_call.c
@@ -118,11 +118,14 @@ static void usage_arg(const char *progname, const char *switchname);
static void usage_error(const char *progname, const char *switchname);
static void usage(const char *progname);
static int get_module(char **mbuf, char **mname);
-static struct hostent* get_hostent(char *host);
static int do_connect(ei_cnode *ec, char *nodename, struct call_flags *flags);
static int read_stdin(char **buf);
static void split_apply_string(char *str, char **mod,
char **fun, char **args);
+static void* ei_chk_malloc(size_t size);
+static void* ei_chk_calloc(size_t nmemb, size_t size);
+static void* ei_chk_realloc(void *old, size_t size);
+static char* ei_chk_strdup(char *s);
/***************************************************************************
@@ -132,7 +135,6 @@ static void split_apply_string(char *str, char **mod,
***************************************************************************/
/* FIXME isn't VxWorks to handle arguments differently? */
-/* FIXME check errors from malloc */
#if !defined(VXWORKS)
int main(int argc, char *argv[])
@@ -165,8 +167,7 @@ int erl_call(int argc, char **argv)
usage_arg(progname, "-sname ");
}
- flags.node = (char *) malloc(strlen(argv[i+1]) + 1);
- strcpy(flags.node, argv[i+1]);
+ flags.node = ei_chk_strdup(argv[i+1]);
i++;
flags.use_long_name = 0;
} else if (strcmp(argv[i], "-name") == 0) { /* -name NAME */
@@ -174,8 +175,7 @@ int erl_call(int argc, char **argv)
usage_arg(progname, "-name ");
}
- flags.node = (char *) malloc(strlen(argv[i+1]) + 1);
- strcpy(flags.node, argv[i+1]);
+ flags.node = ei_chk_strdup(argv[i+1]);
i++;
flags.use_long_name = 1;
} else {
@@ -210,16 +210,14 @@ int erl_call(int argc, char **argv)
usage_arg(progname, "-c ");
}
flags.cookiep = 1;
- flags.cookie = (char *) malloc(strlen(argv[i+1]) + 1);
- strcpy(flags.cookie, argv[i+1]);
+ flags.cookie = ei_chk_strdup(argv[i+1]);
i++;
break;
case 'n':
if (i+1 >= argc) {
usage_arg(progname, "-n ");
}
- flags.node = (char *) malloc(strlen(argv[i+1]) + 1);
- strcpy(flags.node, argv[i+1]);
+ flags.node = ei_chk_strdup(argv[i+1]);
flags.use_long_name = 1;
i++;
break;
@@ -227,24 +225,21 @@ int erl_call(int argc, char **argv)
if (i+1 >= argc) {
usage_arg(progname, "-h ");
}
- flags.hidden = (char *) malloc(strlen(argv[i+1]) + 1);
- strcpy(flags.hidden, argv[i+1]);
+ flags.hidden = ei_chk_strdup(argv[i+1]);
i++;
break;
case 'x':
if (i+1 >= argc) {
usage_arg(progname, "-x ");
}
- flags.script = (char *) malloc(strlen(argv[i+1]) + 1);
- strcpy(flags.script, argv[i+1]);
+ flags.script = ei_chk_strdup(argv[i+1]);
i++;
break;
case 'a':
if (i+1 >= argc) {
usage_arg(progname, "-a ");
}
- flags.apply = (char *) malloc(strlen(argv[i+1]) + 1);
- strcpy(flags.apply, argv[i+1]);
+ flags.apply = ei_chk_strdup(argv[i+1]);
i++;
break;
case '?':
@@ -304,8 +299,7 @@ int erl_call(int argc, char **argv)
if (flags.hidden == NULL) {
/* As default we are c17@gethostname */
i = flags.randomp ? (time(NULL) % 997) : 17;
- /* FIXME allocates to small !!! */
- flags.hidden = (char *) malloc(3 + 2 ); /* c17 or cXYZ */
+ flags.hidden = (char *) ei_chk_malloc(10 + 2 ); /* c17 or cXYZ */
#if defined(VXWORKS)
sprintf(flags.hidden, "c%d",
i < 0 ? (int) taskIdSelf() : i);
@@ -330,17 +324,25 @@ int erl_call(int argc, char **argv)
initWinSock();
#endif
- gethostname(h_hostname, EI_MAXHOSTNAMELEN);
+ if (gethostname(h_hostname, EI_MAXHOSTNAMELEN) < 0) {
+ fprintf(stderr,"erl_call: failed to get host name: %d\n", errno);
+ exit(1);
+ }
if ((hp = ei_gethostbyname(h_hostname)) == 0) {
fprintf(stderr,"erl_call: can't resolve hostname %s\n", h_hostname);
exit(1);
}
- /* If shortnames cut of the name at first '.' */
+ /* If shortnames, cut off the name at first '.' */
if (flags.use_long_name == 0 && (ct = strchr(hp->h_name, '.')) != NULL) {
*ct = '\0';
}
- strcpy(h_hostname, hp->h_name);
+ strncpy(h_hostname, hp->h_name, EI_MAXHOSTNAMELEN);
+ h_hostname[EI_MAXHOSTNAMELEN] = '\0';
memcpy(&h_ipadr.s_addr, *hp->h_addr_list, sizeof(struct in_addr));
+ if (strlen(h_alivename) + strlen(h_hostname) + 2 > sizeof(h_nodename)) {
+ fprintf(stderr,"erl_call: hostname too long: %s\n", h_hostname);
+ exit(1);
+ }
sprintf(h_nodename, "%s@%s", h_alivename, h_hostname);
if (ei_connect_xinit(&ec, h_hostname, h_alivename, h_nodename,
@@ -364,15 +366,20 @@ int erl_call(int argc, char **argv)
* Expand name to a real name (may be ip-address)
*/
/* FIXME better error string */
- if ((hp = get_hostent(host)) == 0) {
- fprintf(stderr,"erl_call: can't get_hostent(%s)\n", host);
+ if ((hp = ei_gethostbyname(host)) == 0) {
+ fprintf(stderr,"erl_call: can't ei_gethostbyname(%s)\n", host);
exit(1);
}
- /* If shortnames cut of the name at first '.' */
+ /* If shortnames, cut off the name at first '.' */
if (flags.use_long_name == 0 && (ct = strchr(hp->h_name, '.')) != NULL) {
*ct = '\0';
}
- strcpy(host_name, hp->h_name);
+ strncpy(host_name, hp->h_name, EI_MAXHOSTNAMELEN);
+ host_name[EI_MAXHOSTNAMELEN] = '\0';
+ if (strlen(flags.node) + strlen(host_name) + 2 > sizeof(nodename)) {
+ fprintf(stderr,"erl_call: nodename too long: %s\n", flags.node);
+ exit(1);
+ }
sprintf(nodename, "%s@%s", flags.node, host_name);
/*
@@ -401,7 +408,7 @@ int erl_call(int argc, char **argv)
ei_encode_empty_list(NULL, &i);
- p = (char *)malloc(i);
+ p = (char *)ei_chk_malloc(i);
i = 0; /* Reset */
ei_encode_empty_list(p, &i);
@@ -426,6 +433,10 @@ int erl_call(int argc, char **argv)
if (flags.modp && (modname != NULL)) {
char fname[256];
+ if (strlen(modname) + 4 + 1 > sizeof(fname)) {
+ fprintf(stderr,"erl_call: module name too long: %s\n", modname);
+ exit(1);
+ }
strcpy(fname, modname);
strcat(fname, ".erl");
@@ -443,7 +454,7 @@ int erl_call(int argc, char **argv)
ei_encode_binary(NULL, &i, module, modsize);
ei_encode_empty_list(NULL, &i);
- p = (char *)malloc(i);
+ p = (char *)ei_chk_malloc(i);
i = 0; /* Reset */
ei_encode_list_header(p, &i, 2);
@@ -476,7 +487,7 @@ int erl_call(int argc, char **argv)
ei_encode_empty_list(NULL, &i);
ei_encode_empty_list(NULL, &i);
- p = (char *)malloc(i);
+ p = (char *)ei_chk_malloc(i);
i = 0; /* Reset */
ei_encode_list_header(p, &i, 2);
@@ -521,7 +532,7 @@ int erl_call(int argc, char **argv)
ei_encode_binary(NULL, &i, evalbuf, len);
ei_encode_empty_list(NULL, &i);
- p = (char *)malloc(i);
+ p = (char *)ei_chk_malloc(i);
i = 0; /* Reset */
ei_encode_list_header(p, &i, 1);
@@ -592,32 +603,6 @@ int erl_call(int argc, char **argv)
*
***************************************************************************/
-/*
- * Get host entry (by address or name)
- */
-/* FIXME: will fail on names like '2fun4you'. */
-static struct hostent* get_hostent(char *host)
-{
- if (isdigit((int)*host)) {
- struct in_addr ip_addr;
- int b1, b2, b3, b4;
- long addr;
-
- /* FIXME: Use inet_aton() (or inet_pton() and get v6 for free). */
- if (sscanf(host, "%d.%d.%d.%d", &b1, &b2, &b3, &b4) != 4) {
- return NULL;
- }
- addr = inet_addr(host);
- ip_addr.s_addr = htonl(addr);
-
- return ei_gethostbyaddr((char *)&ip_addr,sizeof(struct in_addr), AF_INET);
- }
-
- return ei_gethostbyname(host);
-} /* get_hostent */
-
-
-
/*
* This function does only return on success.
@@ -719,32 +704,28 @@ static void split_apply_string(char *str,
EAT(str);
len = str-begin;
- *mod = (char *) calloc(len + 1, sizeof(char));
+ *mod = (char *) ei_chk_calloc(len + 1, sizeof(char));
memcpy(*mod, begin, len);
SKIP_SPACE(str);
if (*str == '\0') {
- *fun = (char *) calloc(strlen(start)+1, sizeof(char));
- strcpy(*fun, start);
- *args = (char *) calloc(strlen(empty_list)+1, sizeof(char));
- strcpy(*args, empty_list);
+ *fun = ei_chk_strdup(start);
+ *args = ei_chk_strdup(empty_list);
return;
}
begin = str;
EAT(str);
len = str-begin;
- *fun = (char *) calloc(len + 1, sizeof(char));
+ *fun = (char *) ei_chk_calloc(len + 1, sizeof(char));
memcpy(*fun, begin, len);
SKIP_SPACE(str);
if (*str == '\0') {
- *args = (char *) calloc(strlen(empty_list)+1, sizeof(char));
- strcpy(*args, empty_list);
+ *args = ei_chk_strdup(empty_list);
return;
}
- *args = (char *) calloc(strlen(str) + 1, sizeof(char));
- strcpy(*args, str);
+ *args = ei_chk_strdup(str);
return;
@@ -760,7 +741,7 @@ static int read_stdin(char **buf)
int bsize = BUFSIZ;
int len = 0;
int i;
- char *tmp = (char *) malloc(bsize);
+ char *tmp = (char *) ei_chk_malloc(bsize);
while (1) {
if ((i = read(0, &tmp[len], bsize-len)) < 0) {
@@ -772,7 +753,7 @@ static int read_stdin(char **buf)
len += i;
if ((len+50) > bsize) {
bsize = len * 2;
- tmp = (char *) realloc(tmp, bsize);
+ tmp = (char *) ei_chk_realloc(tmp, bsize);
} else {
continue;
}
@@ -809,7 +790,7 @@ static int get_module(char **mbuf, char **mname)
}
} /* while */
i = tmp - start;
- *mname = (char *) calloc(i+1, sizeof(char));
+ *mname = (char *) ei_chk_calloc(i+1, sizeof(char));
memcpy(*mname, start, i);
}
if (*mbuf)
@@ -905,3 +886,51 @@ static void initWinSock(void)
}
}
#endif
+
+
+/***************************************************************************
+ *
+ * Utility functions
+ *
+ ***************************************************************************/
+
+static void* ei_chk_malloc(size_t size)
+{
+ void *p = malloc(size);
+ if (p == NULL) {
+ fprintf(stderr,"erl_call: insufficient memory\n");
+ exit(1);
+ }
+ return p;
+}
+
+static void* ei_chk_calloc(size_t nmemb, size_t size)
+{
+ void *p = calloc(nmemb, size);
+ if (p == NULL) {
+ fprintf(stderr,"erl_call: insufficient memory\n");
+ exit(1);
+ }
+ return p;
+}
+
+static void* ei_chk_realloc(void *old, size_t size)
+{
+ void *p = realloc(old, size);
+ if (!p) {
+ fprintf(stderr, "erl_call: cannot reallocate %u bytes of memory from %p\n",
+ (unsigned) size, old);
+ exit (1);
+ }
+ return p;
+}
+
+static char* ei_chk_strdup(char *s)
+{
+ char *p = strdup(s);
+ if (p == NULL) {
+ fprintf(stderr,"erl_call: insufficient memory\n");
+ exit(1);
+ }
+ return p;
+}
diff --git a/lib/erl_interface/src/registry/reg_dump.c b/lib/erl_interface/src/registry/reg_dump.c
index 50a6949177..dfec96b43c 100644
--- a/lib/erl_interface/src/registry/reg_dump.c
+++ b/lib/erl_interface/src/registry/reg_dump.c
@@ -157,7 +157,7 @@ static int mn_send_delete(int fd, erlang_pid *mnesia, const char *key)
int len = strlen(key) + 32; /* 32 is a slight overestimate */
if (len > EISMALLBUF)
- if (!(dbuf = malloc(index)))
+ if (!(dbuf = malloc(len)))
return -1;
msgbuf = (dbuf ? dbuf : sbuf);
@@ -187,7 +187,7 @@ static int mn_send_write(int fd, erlang_pid *mnesia, const char *key, ei_reg_obj
int len = 32 + keylen + obj->size;
if (len > EISMALLBUF)
- if (!(dbuf = malloc(index)))
+ if (!(dbuf = malloc(len)))
return -1;
msgbuf = (dbuf ? dbuf : sbuf);
diff --git a/lib/erl_interface/src/registry/reg_restore.c b/lib/erl_interface/src/registry/reg_restore.c
index 27918d2364..aeb33c784a 100644
--- a/lib/erl_interface/src/registry/reg_restore.c
+++ b/lib/erl_interface/src/registry/reg_restore.c
@@ -266,7 +266,7 @@ int ei_reg_restore(int fd, ei_reg *reg, const char *mntab)
/* make sure receive buffer can handle largest expected message */
len = maxkey + maxobj + 512;
if (len > EISMALLBUF)
- if (!(dbuf = malloc(index))) {
+ if (!(dbuf = malloc(len))) {
ei_send_exit(fd,&self,&mnesia,"cannot allocate space for incoming data");
return -1;
}
diff --git a/lib/erl_interface/test/ei_accept_SUITE.erl b/lib/erl_interface/test/ei_accept_SUITE.erl
index bc83d6a62e..a97c874e5f 100644
--- a/lib/erl_interface/test/ei_accept_SUITE.erl
+++ b/lib/erl_interface/test/ei_accept_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -31,7 +31,7 @@
all(suite) -> [ei_accept, ei_threaded_accept].
init_per_testcase(_Case, Config) ->
- Dog = ?t:timetrap(?t:minutes(0.25)),
+ Dog = ?t:timetrap(?t:seconds(30)),
[{watchdog, Dog}|Config].
fin_per_testcase(_Case, Config) ->
@@ -43,8 +43,6 @@ ei_accept(Config) when is_list(Config) ->
?line P = runner:start(?interpret),
?line 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0),
-% ?line AMsg={a,[message, with], " strings in it!", [-12, -23], 1.001},
- %% shouldn't this be a bif or function or something?
?line Myname= hd(tl(string:tokens(atom_to_list(node()), "@"))),
?line io:format("Myname ~p ~n", [Myname]),
?line EINode= list_to_atom("c42@"++Myname),
@@ -52,9 +50,13 @@ ei_accept(Config) when is_list(Config) ->
?line Self= self(),
?line TermToSend= {call, Self, "Test"},
?line F= fun() ->
- timer:sleep(500),
- {any, EINode} ! TermToSend,
- Self ! sent_ok,
+ case waitfornode("c42",20) of
+ true ->
+ {any, EINode} ! TermToSend,
+ Self ! sent_ok;
+ false ->
+ Self ! never_published
+ end,
ok
end,
@@ -72,7 +74,7 @@ ei_accept(Config) when is_list(Config) ->
after 1000 ->
io:format("timeout ~n")
end,
- ?line ok= ei_unpublish(P),
+ ?line runner:finish(P),
ok.
ei_threaded_accept(Config) when is_list(Config) ->
@@ -90,12 +92,29 @@ ei_threaded_accept(Config) when is_list(Config) ->
|| I <- lists:seq(0, N-1) ],
ok.
+waitfornode(String,0) ->
+ io:format("~s never published itself.~n",[String]),
+ false;
+waitfornode(String,N) ->
+ Registered = [X || {X,_} <- element(2,erl_epmd:names())],
+ case lists:member(String,Registered) of
+ true ->
+ true;
+ false ->
+ timer:sleep(1000),
+ waitfornode(String,N-1)
+ end.
+
send_rec_einode(N, TestServerPid) ->
?line Myname= hd(tl(string:tokens(atom_to_list(node()), "@"))),
- ?line EINode= list_to_atom("eiacc" ++ integer_to_list(N) ++ "@" ++ Myname),
+ ?line FirstPart = "eiacc" ++ integer_to_list(N),
+ ?line EINode= list_to_atom(FirstPart ++ "@" ++ Myname),
?line io:format("EINode ~p ~n", [EINode]),
?line Self= self(),
- ?line timer:sleep(10*1000),
+ ?line case waitfornode(FirstPart,20) of
+ true -> ok;
+ false -> test_server:fail({never_published,EINode})
+ end,
?line {any, EINode} ! Self,
?line receive
{N,_}=X ->
@@ -136,13 +155,6 @@ ei_receive(P, Fd) ->
{term, T}= get_term(P),
T.
-ei_unpublish(P) ->
- send_command(P, ei_unpublish, []),
- case get_term(P) of
- {term,{0, _}} -> ok;
- {term,{_X, Errno}} -> {error,Errno}
- end.
-
send_command(P, Name, Args) ->
runner:send_term(P, {Name,list_to_tuple(Args)}).
diff --git a/lib/erl_interface/test/ei_connect_SUITE.erl b/lib/erl_interface/test/ei_connect_SUITE.erl
index 56f478edad..fe82a73ef9 100644
--- a/lib/erl_interface/test/ei_connect_SUITE.erl
+++ b/lib/erl_interface/test/ei_connect_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -103,10 +103,12 @@ ei_threaded_send(Config) when is_list(Config) ->
?line Einode = filename:join(?config(data_dir, Config), "einode"),
?line N = 15,
?line Host = atom_to_list(node()),
- ?line spawn_link(fun() -> start_einode(Einode, N, Host) end),
?line TestServerPid = self(),
?line [ spawn_link(fun() -> rec_einode(I, TestServerPid) end)
|| I <- lists:seq(0, N-1) ],
+ ?line [ receive {I,registered} -> ok end
+ || I <- lists:seq(0, N-1) ],
+ ?line spawn_link(fun() -> start_einode(Einode, N, Host) end),
?line [ receive I -> ok end
|| I <- lists:seq(0, N-1) ],
ok.
@@ -114,6 +116,7 @@ ei_threaded_send(Config) when is_list(Config) ->
rec_einode(N, TestServerPid) ->
?line Regname = list_to_atom("mth"++integer_to_list(N)),
?line register(Regname, self()),
+ ?line TestServerPid ! {N, registered},
?line io:format("~p waiting~n", [Regname]),
?line receive
X ->
diff --git a/lib/erl_interface/test/ei_format_SUITE.erl b/lib/erl_interface/test/ei_format_SUITE.erl
index 7871f07ae9..cbe9fa52d7 100644
--- a/lib/erl_interface/test/ei_format_SUITE.erl
+++ b/lib/erl_interface/test/ei_format_SUITE.erl
@@ -155,7 +155,7 @@ format_wo_ver(suite) -> [];
format_wo_ver(Config) when is_list(Config) ->
?line P = runner:start(?format_wo_ver),
- ?line {term, [{a, "b"}, {c, 10}]} = get_term(P),
+ ?line {term, [-1, 2, {a, "b"}, {c, 10}]} = get_term(P),
?line runner:recv_eot(P),
ok.
diff --git a/lib/erl_interface/test/ei_format_SUITE_data/ei_format_test.c b/lib/erl_interface/test/ei_format_SUITE_data/ei_format_test.c
index a969ded3dc..ecdce402f5 100644
--- a/lib/erl_interface/test/ei_format_SUITE_data/ei_format_test.c
+++ b/lib/erl_interface/test/ei_format_SUITE_data/ei_format_test.c
@@ -176,7 +176,7 @@ TESTCASE(format_wo_ver) {
ei_x_buff x;
ei_x_new (&x);
- ei_x_format(&x, "[{~a,~s},{~a,~i}]", "a", "b", "c", 10);
+ ei_x_format(&x, "[-1, +2, {~a,~s},{~a,~i}]", "a", "b", "c", 10);
send_bin_term(&x);
free(x.buff);
diff --git a/lib/erl_interface/vsn.mk b/lib/erl_interface/vsn.mk
index 672b1be55f..6c664959a3 100644
--- a/lib/erl_interface/vsn.mk
+++ b/lib/erl_interface/vsn.mk
@@ -1 +1 @@
-EI_VSN = 3.7
+EI_VSN = 3.7.1.1
diff --git a/lib/et/doc/src/et.xml b/lib/et/doc/src/et.xml
index 9b170dd7d9..5e3453c348 100644
--- a/lib/et/doc/src/et.xml
+++ b/lib/et/doc/src/et.xml
@@ -29,6 +29,7 @@
<checked></checked>
<date></date>
<rev>%VSN%</rev>
+ <file>et</file>
</header>
<module>et</module>
<modulesummary>Main API of the Event Trace (ET) application</modulesummary>
diff --git a/lib/et/doc/src/et_collector.xml b/lib/et/doc/src/et_collector.xml
index 88c478c89a..e9885dcbb3 100644
--- a/lib/et/doc/src/et_collector.xml
+++ b/lib/et/doc/src/et_collector.xml
@@ -29,6 +29,7 @@
<checked></checked>
<date></date>
<rev>%VSN%</rev>
+ <file>et_collector.xml</file>
</header>
<module>et_collector</module>
<modulesummary>Collect trace events and provide a backing storage appropriate for iteration </modulesummary>
diff --git a/lib/et/doc/src/et_selector.xml b/lib/et/doc/src/et_selector.xml
index dd12166d85..34203306bb 100644
--- a/lib/et/doc/src/et_selector.xml
+++ b/lib/et/doc/src/et_selector.xml
@@ -29,6 +29,7 @@
<checked></checked>
<date></date>
<rev>%VSN%</rev>
+ <file>et_selector.xml</file>
</header>
<module>et_selector</module>
<modulesummary>Define event transforms and trace patterns</modulesummary>
diff --git a/lib/et/doc/src/et_tutorial.xmlsrc b/lib/et/doc/src/et_tutorial.xmlsrc
index c72234a587..b0e2bf4af6 100644
--- a/lib/et/doc/src/et_tutorial.xmlsrc
+++ b/lib/et/doc/src/et_tutorial.xmlsrc
@@ -29,6 +29,7 @@
<checked></checked>
<date></date>
<rev>%VSN%</rev>
+ <file>et_tutorial.xml</file>
</header>
<section>
diff --git a/lib/et/doc/src/et_viewer.xml b/lib/et/doc/src/et_viewer.xml
index c16e5b8869..d4cfbdfa31 100644
--- a/lib/et/doc/src/et_viewer.xml
+++ b/lib/et/doc/src/et_viewer.xml
@@ -29,6 +29,7 @@
<checked></checked>
<date></date>
<rev>%VSN%</rev>
+ <file>et_viewer.xml</file>
</header>
<module>et_viewer</module>
<modulesummary>Displays a sequence chart for trace events (messages/actions)</modulesummary>
diff --git a/lib/et/doc/src/notes.xml b/lib/et/doc/src/notes.xml
index 8611955d3d..4ce7548414 100644
--- a/lib/et/doc/src/notes.xml
+++ b/lib/et/doc/src/notes.xml
@@ -36,6 +36,32 @@
one section in this document. The title of each section is the
version number of <c>Event Tracer (ET)</c>.</p>
+<section><title>ET 1.4.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fixed broken links in the documentation. </p>
+ <p>
+ Own Id: OTP-8796</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Fixed gui crash on windows.</p>
+ <p>
+ Own Id: OTP-8830</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>ET 1.4</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/et/src/et_wx_viewer.erl b/lib/et/src/et_wx_viewer.erl
index 5cd3563aed..d42f8c0c86 100644
--- a/lib/et/src/et_wx_viewer.erl
+++ b/lib/et/src/et_wx_viewer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1233,7 +1233,7 @@ create_main_window(S) ->
[{flag, ?wxEXPAND}]),
CanvasSizer = wxBoxSizer:new(?wxHORIZONTAL),
- Canvas = wxPanel:new(Panel, []),
+ Canvas = wxPanel:new(Panel, [{style, ?wxFULL_REPAINT_ON_RESIZE}]),
{CanvasW,CanvasH} = wxPanel:getSize(Canvas),
ScrollBar = wxScrollBar:new(Panel, ?wxID_ANY, [{style, ?wxSB_VERTICAL}]),
@@ -1244,7 +1244,13 @@ create_main_window(S) ->
wxPanel:connect(Canvas, left_up),
wxPanel:connect(Canvas, right_up),
wxPanel:connect(Canvas, size),
- wxPanel:connect(Canvas, paint),
+ Self = self(),
+ wxPanel:connect(Canvas, paint, [{callback, %% Needed on windows
+ fun(Ev, _) ->
+ DC = wxPaintDC:new(Canvas),
+ wxPaintDC:destroy(DC),
+ Self ! Ev
+ end}]),
wxPanel:connect(Canvas, key_down),
wxPanel:connect(Canvas, kill_focus),
wxPanel:connect(Canvas, enter_window, [{skip, true}]),
@@ -1437,6 +1443,7 @@ create_help_menu(Bar) ->
clear_canvas(S) ->
DC = wxClientDC:new(S#state.canvas),
+ wxDC:setBackground(DC, ?wxWHITE_BRUSH), %% Needed on mac
wxDC:clear(DC),
{CanvasW, CanvasH} = wxPanel:getSize(S#state.canvas),
wxSizer:recalcSizes(S#state.canvas_sizer),
diff --git a/lib/et/test/Makefile b/lib/et/test/Makefile
index 9aedf96ce9..7227ae8fd8 100644
--- a/lib/et/test/Makefile
+++ b/lib/et/test/Makefile
@@ -72,7 +72,8 @@ release_spec: opt
release_tests_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) et.spec $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)
- $(INSTALL_PROGRAM) ett $(INSTALL_PROGS) $(RELSYSDIR)
+ $(INSTALL_SCRIPT) ett $(RELSYSDIR)
+ $(INSTALL_DATA) $(INSTALL_PROGS) $(RELSYSDIR)
# chmod -f -R u+w $(RELSYSDIR)
# @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
diff --git a/lib/et/vsn.mk b/lib/et/vsn.mk
index b7d65b12a2..b5b7fa52f4 100644
--- a/lib/et/vsn.mk
+++ b/lib/et/vsn.mk
@@ -1,24 +1 @@
-# This is an -*-makefile-*- file.
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2002-2010. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-
-ET_VSN = 1.4
-TICKETS = OTP-8058
-
-TICKETS_1_3_3 = OTP-8201
-TICKETS_1_3_2 = OTP-8078
-TICKETS_1_3_1 = OTP-7830
+ET_VSN = 1.4.1
diff --git a/lib/gs/doc/src/gs.xml b/lib/gs/doc/src/gs.xml
index b1c7e505dc..f2182fc673 100644
--- a/lib/gs/doc/src/gs.xml
+++ b/lib/gs/doc/src/gs.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2000</year>
- <year>2007</year>
+ <year>2010</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -32,6 +32,18 @@
<module>gs</module>
<modulesummary>The Graphics System for Erlang.</modulesummary>
<description>
+ <warning>
+ <p>
+ GS is not recommended for use in new applications.
+ Instead we recommend WX for applications that need a
+ graphical user interface.
+ </p>
+ <p>
+ GS is not maintained and we plan to deprecate and remove it from
+ the distribution as soon as possible, maybe already in the next
+ major release (R15).
+ </p>
+ </warning>
<p>The Graphics System, GS, is easy to learn and
designed to be portable to many different platforms.</p>
<p>In the description below, the type <c><![CDATA[gsobj()]]></c> denotes a
diff --git a/lib/gs/doc/src/gs_chapter1.xml b/lib/gs/doc/src/gs_chapter1.xml
index cfcae94f7c..912d6e1ef9 100644
--- a/lib/gs/doc/src/gs_chapter1.xml
+++ b/lib/gs/doc/src/gs_chapter1.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2000</year><year>2009</year>
+ <year>2000</year><year>2010</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,18 @@
<section>
<title>Introduction</title>
+ <warning>
+ <p>
+ GS is not recommended for use in new applications.
+ Instead we recommend WX for applications that need a
+ graphical user interface.
+ </p>
+ <p>
+ GS is not maintained and we plan to deprecate and remove it from
+ the distribution as soon as possible, maybe already in the next
+ major release (R15).
+ </p>
+ </warning>
<p>This section describes the general graphics interface to Erlang. This system was designed with the following requirements in mind:</p>
<list type="bulleted">
<item>a graphics system which is easy to learn</item>
diff --git a/lib/gs/doc/src/notes.xml b/lib/gs/doc/src/notes.xml
index 352c335e23..744efbd4fc 100644
--- a/lib/gs/doc/src/notes.xml
+++ b/lib/gs/doc/src/notes.xml
@@ -30,7 +30,27 @@
</header>
<p>This document describes the changes made to the GS application.</p>
- <section>
+ <section><title>GS 1.5.13</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The documentation for GS is updated with the warning that
+ it should not be used in new applications. GS is planned
+ to be deprecated soon and might be removed from the
+ distribution already in the next major release (R15). For
+ graphical applications we recommend the use of WX
+ instead.</p>
+ <p>
+ Own Id: OTP-8824</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section>
<title>GS 1.5.10</title>
<section>
diff --git a/lib/gs/vsn.mk b/lib/gs/vsn.mk
index 35976d556a..4c91857572 100644
--- a/lib/gs/vsn.mk
+++ b/lib/gs/vsn.mk
@@ -1,2 +1,2 @@
-GS_VSN = 1.5.12
+GS_VSN = 1.5.13
diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl
index 1f0247a040..835f9a205a 100644
--- a/lib/hipe/cerl/erl_bif_types.erl
+++ b/lib/hipe/cerl/erl_bif_types.erl
@@ -1219,7 +1219,7 @@ type(erlang, monitor_node, 3, Xs) ->
strict(arg_types(erlang, monitor_node, 3), Xs,
fun (_) -> t_atom('true') end);
type(erlang, nif_error, 1, _) ->
- t_any();
+ t_any(); % this BIF and the next one are stubs for NIFs and never return
type(erlang, nif_error, 2, Xs) ->
strict(arg_types(erlang, nif_error, 2), Xs, fun (_) -> t_any() end);
type(erlang, node, 0, _) -> t_node();
@@ -1638,7 +1638,6 @@ type(erlang, system_info, 1, Xs) ->
t_non_neg_integer()])]));
['allocator'] ->
t_tuple([t_sup([t_atom('undefined'),
- t_atom('elib_malloc'),
t_atom('glibc')]),
t_list(t_integer()),
t_list(t_atom()),
@@ -1659,9 +1658,8 @@ type(erlang, system_info, 1, Xs) ->
t_binary();
['dist_ctrl'] ->
t_list(t_tuple([t_atom(), t_sup([t_pid(), t_port])]));
- ['elib_malloc'] ->
- t_sup([t_atom('false'),
- t_list(t_tuple([t_atom(), t_any()]))]);
+ %% elib_malloc is intentionally not included,
+ %% because it scheduled for removal in R15.
['endian'] ->
t_endian();
['fullsweep_after'] ->
@@ -1972,7 +1970,25 @@ type(ets, slot, 2, Xs) ->
strict(arg_types(ets, slot, 2), Xs,
fun (_) -> t_sup(t_list(t_tuple()), t_atom('$end_of_table')) end);
type(ets, update_counter, 3, Xs) ->
- strict(arg_types(ets, update_counter, 3), Xs, fun (_) -> t_integer() end);
+ strict(arg_types(ets, update_counter, 3), Xs,
+ fun ([_, _, Op]) ->
+ case t_is_integer(Op) of
+ true -> t_integer();
+ false ->
+ case t_is_tuple(Op) of
+ true -> t_integer();
+ false ->
+ case t_is_list(Op) of
+ true -> t_list(t_integer());
+ false ->
+ case t_is_nil(Op) of
+ true -> t_nil();
+ false -> t_sup([t_integer(), t_list(t_integer())])
+ end
+ end
+ end
+ end
+ end);
type(ets, update_element, 3, Xs) ->
strict(arg_types(ets, update_element, 3), Xs, fun (_) -> t_boolean() end);
%%-- file ---------------------------------------------------------------------
@@ -4183,10 +4199,9 @@ arg_types(ets, setopts, 2) ->
t_tuple([t_atom('heir'), t_atom('none')])),
[t_tab(), t_sup(Opt, t_list(Opt))];
arg_types(ets, update_counter, 3) ->
- [t_tab(), t_any(), t_sup(t_integer(),
- t_sup(t_tuple([t_integer(), t_integer()]),
- t_tuple([t_integer(), t_integer(),
- t_integer(), t_integer()])))];
+ Int = t_integer(),
+ UpdateOp = t_sup(t_tuple([Int, Int]), t_tuple([Int, Int, Int, Int])),
+ [t_tab(), t_any(), t_sup([UpdateOp, t_list(UpdateOp), Int])];
arg_types(ets, update_element, 3) ->
PosValue = t_tuple([t_integer(), t_any()]),
[t_tab(), t_any(), t_sup(PosValue, t_list(PosValue))];
diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl
index 9a40be6d14..4dd124a457 100644
--- a/lib/hipe/cerl/erl_types.erl
+++ b/lib/hipe/cerl/erl_types.erl
@@ -29,7 +29,7 @@
%% In late 2008, Manouk Manoukian and Kostis Sagonas added support for
%% opaque types to the structure-based representation of types.
%% During February and March 2009, Kostis Sagonas significantly
-%% cleaned up the type representation added spec declarations.
+%% cleaned up the type representation and added spec declarations.
%%
%% ======================================================================
@@ -714,12 +714,13 @@ t_solve_remote_type(#remote{mod = RemMod, name = Name, args = Args} = RemType,
case lookup_type(Name, RemDict) of
{type, {_Mod, Type, ArgNames}} when ArgsLen =:= length(ArgNames) ->
{NewType, NewCycle, NewRR} =
- case unfold(RemType, C) of
+ case can_unfold_more(RemType, C) of
true ->
List = lists:zip(ArgNames, Args),
TmpVarDict = dict:from_list(List),
{t_from_form(Type, RemDict, TmpVarDict), [RemType|C], []};
- false -> {t_any(), C, [RemType]}
+ false ->
+ {t_any(), C, [RemType]}
end,
{RT, RR} = t_solve_remote(NewType, ET, R, NewCycle),
RetRR = NewRR ++ RR,
@@ -733,9 +734,11 @@ t_solve_remote_type(#remote{mod = RemMod, name = Name, args = Args} = RemType,
List = lists:zip(ArgNames, Args),
TmpVarDict = dict:from_list(List),
{Rep, NewCycle, NewRR} =
- case unfold(RemType, C) of
- true -> {t_from_form(Type, RemDict, TmpVarDict), [RemType|C], []};
- false -> {t_any(), C, [RemType]}
+ case can_unfold_more(RemType, C) of
+ true ->
+ {t_from_form(Type, RemDict, TmpVarDict), [RemType|C], []};
+ false ->
+ {t_any(), C, [RemType]}
end,
{NewRep, RR} = t_solve_remote(Rep, ET, R, NewCycle),
RetRR = NewRR ++ RR,
@@ -2388,9 +2391,9 @@ inf_tuple_sets([{Arity, Tuples1}|Left1], [{Arity, Tuples2}|Left2], Acc, Mode) ->
[] -> inf_tuple_sets(Left1, Left2, Acc, Mode);
NewTuples -> inf_tuple_sets(Left1, Left2, [{Arity, NewTuples}|Acc], Mode)
end;
-inf_tuple_sets(L1 = [{Arity1, _}|Left1], L2 = [{Arity2, _}|Left2], Acc, Mode) ->
- if Arity1 < Arity2 -> inf_tuple_sets(Left1, L2, Acc, Mode);
- Arity1 > Arity2 -> inf_tuple_sets(L1, Left2, Acc, Mode)
+inf_tuple_sets([{Arity1, _}|Ts1] = L1, [{Arity2, _}|Ts2] = L2, Acc, Mode) ->
+ if Arity1 < Arity2 -> inf_tuple_sets(Ts1, L2, Acc, Mode);
+ Arity1 > Arity2 -> inf_tuple_sets(L1, Ts2, Acc, Mode)
end;
inf_tuple_sets([], _, Acc, _Mode) -> lists:reverse(Acc);
inf_tuple_sets(_, [], Acc, _Mode) -> lists:reverse(Acc).
@@ -2406,17 +2409,17 @@ inf_tuples_in_sets(L1, [?tuple(Elements2, _, ?any)], Mode) ->
inf_tuples_in_sets(L1, L2, Mode) ->
inf_tuples_in_sets(L1, L2, [], Mode).
-inf_tuples_in_sets([?tuple(Elements1, Arity, Tag)|Left1],
- [?tuple(Elements2, Arity, Tag)|Left2], Acc, Mode) ->
+inf_tuples_in_sets([?tuple(Elements1, Arity, Tag)|Ts1],
+ [?tuple(Elements2, Arity, Tag)|Ts2], Acc, Mode) ->
case t_inf_lists_strict(Elements1, Elements2, Mode) of
- bottom -> inf_tuples_in_sets(Left1, Left2, Acc, Mode);
- NewElements ->
- inf_tuples_in_sets(Left1, Left2, [?tuple(NewElements, Arity, Tag)|Acc], Mode)
+ bottom -> inf_tuples_in_sets(Ts1, Ts2, Acc, Mode);
+ NewElements ->
+ inf_tuples_in_sets(Ts1, Ts2, [?tuple(NewElements, Arity, Tag)|Acc], Mode)
end;
-inf_tuples_in_sets([?tuple(_, _, Tag1)|Left1] = L1,
- [?tuple(_, _, Tag2)|Left2] = L2, Acc, Mode) ->
- if Tag1 < Tag2 -> inf_tuples_in_sets(Left1, L2, Acc, Mode);
- Tag1 > Tag2 -> inf_tuples_in_sets(L1, Left2, Acc, Mode)
+inf_tuples_in_sets([?tuple(_, _, Tag1)|Ts1] = L1,
+ [?tuple(_, _, Tag2)|Ts2] = L2, Acc, Mode) ->
+ if Tag1 < Tag2 -> inf_tuples_in_sets(Ts1, L2, Acc, Mode);
+ Tag1 > Tag2 -> inf_tuples_in_sets(L1, Ts2, Acc, Mode)
end;
inf_tuples_in_sets([], _, Acc, _Mode) -> lists:reverse(Acc);
inf_tuples_in_sets(_, [], Acc, _Mode) -> lists:reverse(Acc).
@@ -2791,13 +2794,13 @@ t_subtract(?opaque(Set1), ?opaque(Set2)) ->
Set -> ?opaque(Set)
end;
t_subtract(?matchstate(Pres1, Slots1), ?matchstate(Pres2, _Slots2)) ->
- Pres = t_subtract(Pres1,Pres2),
+ Pres = t_subtract(Pres1, Pres2),
case t_is_none(Pres) of
true -> ?none;
- false -> ?matchstate(Pres,Slots1)
+ false -> ?matchstate(Pres, Slots1)
end;
-t_subtract(?matchstate(Present,Slots),_) ->
- ?matchstate(Present,Slots);
+t_subtract(?matchstate(Present, Slots), _) ->
+ ?matchstate(Present, Slots);
t_subtract(?nil, ?nil) ->
?none;
t_subtract(?nil, ?nonempty_list(_, _)) ->
@@ -3390,211 +3393,263 @@ t_from_form(Form, RecDict) ->
-spec t_from_form(parse_form(), dict(), dict()) -> erl_type().
t_from_form(Form, RecDict, VarDict) ->
- {T, _R} = t_from_form(Form, [], RecDict, VarDict),
+ {T, _R} = t_from_form(Form, [], false, RecDict, VarDict),
T.
-type type_names() :: [{'type' | 'opaque' | 'record', atom()}].
--spec t_from_form(parse_form(), type_names(), dict(), dict()) ->
+-spec t_from_form(parse_form(), type_names(), boolean(), dict(), dict()) ->
{erl_type(), type_names()}.
-t_from_form({var, _L, '_'}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({var, _L, '_'}, _TypeNames, _InOpaque, _RecDict, _VarDict) ->
{t_any(), []};
-t_from_form({var, _L, Name}, _TypeNames, _RecDict, VarDict) ->
+t_from_form({var, _L, Name}, _TypeNames, _InOpaque, _RecDict, VarDict) ->
case dict:find(Name, VarDict) of
error -> {t_var(Name), []};
{ok, Val} -> {Val, []}
end;
-t_from_form({ann_type, _L, [_Var, Type]}, TypeNames, RecDict, VarDict) ->
- t_from_form(Type, TypeNames, RecDict, VarDict);
-t_from_form({paren_type, _L, [Type]}, TypeNames, RecDict, VarDict) ->
- t_from_form(Type, TypeNames, RecDict, VarDict);
+t_from_form({ann_type, _L, [_Var, Type]}, TypeNames, InOpaque, RecDict,
+ VarDict) ->
+ t_from_form(Type, TypeNames, InOpaque, RecDict, VarDict);
+t_from_form({paren_type, _L, [Type]}, TypeNames, InOpaque, RecDict,
+ VarDict) ->
+ t_from_form(Type, TypeNames, InOpaque, RecDict, VarDict);
t_from_form({remote_type, _L, [{atom, _, Module}, {atom, _, Type}, Args]},
- TypeNames, RecDict, VarDict) ->
- {L, R} = list_from_form(Args, TypeNames, RecDict, VarDict),
+ TypeNames, InOpaque, RecDict, VarDict) ->
+ {L, R} = list_from_form(Args, TypeNames, InOpaque, RecDict, VarDict),
{t_remote(Module, Type, L), R};
-t_from_form({atom, _L, Atom}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({atom, _L, Atom}, _TypeNames, _InOpaque, _RecDict, _VarDict) ->
{t_atom(Atom), []};
-t_from_form({integer, _L, Int}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({integer, _L, Int}, _TypeNames, _InOpaque, _RecDict, _VarDict) ->
{t_integer(Int), []};
-t_from_form({op, _L, _Op, _Arg} = Op, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({op, _L, _Op, _Arg} = Op, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
case erl_eval:partial_eval(Op) of
{integer, _, Val} ->
{t_integer(Val), []};
- _ -> throw({error, io_lib:format("Unable evaluate type ~w\n", [Op])})
+ _ -> throw({error, io_lib:format("Unable to evaluate type ~w\n", [Op])})
end;
-t_from_form({op, _L, _Op, _Arg1, _Arg2} = Op, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({op, _L, _Op, _Arg1, _Arg2} = Op, _TypeNames, _InOpaque,
+ _RecDict, _VarDict) ->
case erl_eval:partial_eval(Op) of
{integer, _, Val} ->
{t_integer(Val), []};
- _ -> throw({error, io_lib:format("Unable evaluate type ~w\n", [Op])})
+ _ -> throw({error, io_lib:format("Unable to evaluate type ~w\n", [Op])})
end;
-t_from_form({type, _L, any, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, any, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_any(), []};
-t_from_form({type, _L, arity, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, arity, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_arity(), []};
-t_from_form({type, _L, array, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, array, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_array(), []};
-t_from_form({type, _L, atom, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, atom, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_atom(), []};
-t_from_form({type, _L, binary, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, binary, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_binary(), []};
t_from_form({type, _L, binary, [Base, Unit]} = Type,
- _TypeNames, _RecDict, _VarDict) ->
+ _TypeNames, _InOpaque, _RecDict, _VarDict) ->
case {erl_eval:partial_eval(Base), erl_eval:partial_eval(Unit)} of
{{integer, _, BaseVal},
{integer, _, UnitVal}}
when BaseVal >= 0, UnitVal >= 0 ->
{t_bitstr(UnitVal, BaseVal), []};
- _ -> throw({error, io_lib:format("Unable evaluate type ~w\n", [Type])})
+ _ -> throw({error, io_lib:format("Unable to evaluate type ~w\n", [Type])})
end;
-t_from_form({type, _L, bitstring, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, bitstring, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_bitstr(), []};
-t_from_form({type, _L, bool, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, bool, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_boolean(), []}; % XXX: Temporarily
-t_from_form({type, _L, boolean, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, boolean, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_boolean(), []};
-t_from_form({type, _L, byte, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, byte, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_byte(), []};
-t_from_form({type, _L, char, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, char, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_char(), []};
-t_from_form({type, _L, dict, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, dict, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_dict(), []};
-t_from_form({type, _L, digraph, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, digraph, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_digraph(), []};
-t_from_form({type, _L, float, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, float, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_float(), []};
-t_from_form({type, _L, function, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, function, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_fun(), []};
-t_from_form({type, _L, 'fun', []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, 'fun', []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_fun(), []};
t_from_form({type, _L, 'fun', [{type, _, any, []}, Range]}, TypeNames,
- RecDict, VarDict) ->
- {T, R} = t_from_form(Range, TypeNames, RecDict, VarDict),
+ InOpaque, RecDict, VarDict) ->
+ {T, R} = t_from_form(Range, TypeNames, InOpaque, RecDict, VarDict),
{t_fun(T), R};
t_from_form({type, _L, 'fun', [{type, _, product, Domain}, Range]},
- TypeNames, RecDict, VarDict) ->
- {L, R1} = list_from_form(Domain, TypeNames, RecDict, VarDict),
- {T, R2} = t_from_form(Range, TypeNames, RecDict, VarDict),
+ TypeNames, InOpaque, RecDict, VarDict) ->
+ {L, R1} = list_from_form(Domain, TypeNames, InOpaque, RecDict, VarDict),
+ {T, R2} = t_from_form(Range, TypeNames, InOpaque, RecDict, VarDict),
{t_fun(L, T), R1 ++ R2};
-t_from_form({type, _L, gb_set, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, gb_set, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_gb_set(), []};
-t_from_form({type, _L, gb_tree, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, gb_tree, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_gb_tree(), []};
-t_from_form({type, _L, identifier, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, identifier, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_identifier(), []};
-t_from_form({type, _L, integer, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, integer, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_integer(), []};
-t_from_form({type, _L, iodata, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, iodata, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_iodata(), []};
-t_from_form({type, _L, iolist, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, iolist, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_iolist(), []};
-t_from_form({type, _L, list, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, list, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_list(), []};
-t_from_form({type, _L, list, [Type]}, TypeNames, RecDict, VarDict) ->
- {T, R} = t_from_form(Type, TypeNames, RecDict, VarDict),
+t_from_form({type, _L, list, [Type]}, TypeNames, InOpaque, RecDict,
+ VarDict) ->
+ {T, R} = t_from_form(Type, TypeNames, InOpaque, RecDict, VarDict),
{t_list(T), R};
-t_from_form({type, _L, mfa, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, mfa, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_mfa(), []};
-t_from_form({type, _L, module, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, module, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_module(), []};
-t_from_form({type, _L, nil, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, nil, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_nil(), []};
-t_from_form({type, _L, neg_integer, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, neg_integer, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_neg_integer(), []};
-t_from_form({type, _L, non_neg_integer, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, non_neg_integer, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_non_neg_integer(), []};
-t_from_form({type, _L, no_return, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, no_return, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_unit(), []};
-t_from_form({type, _L, node, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, node, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_node(), []};
-t_from_form({type, _L, none, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, none, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_none(), []};
-t_from_form({type, _L, nonempty_list, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, nonempty_list, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_nonempty_list(), []};
-t_from_form({type, _L, nonempty_list, [Type]}, TypeNames, RecDict, VarDict) ->
- {T, R} = t_from_form(Type, TypeNames, RecDict, VarDict),
+t_from_form({type, _L, nonempty_list, [Type]}, TypeNames, InOpaque, RecDict,
+ VarDict) ->
+ {T, R} = t_from_form(Type, TypeNames, InOpaque, RecDict, VarDict),
{t_nonempty_list(T), R};
t_from_form({type, _L, nonempty_improper_list, [Cont, Term]}, TypeNames,
- RecDict, VarDict) ->
- {T1, R1} = t_from_form(Cont, TypeNames, RecDict, VarDict),
- {T2, R2} = t_from_form(Term, TypeNames, RecDict, VarDict),
+ InOpaque, RecDict, VarDict) ->
+ {T1, R1} = t_from_form(Cont, TypeNames, InOpaque, RecDict, VarDict),
+ {T2, R2} = t_from_form(Term, TypeNames, InOpaque, RecDict, VarDict),
{t_cons(T1, T2), R1 ++ R2};
t_from_form({type, _L, nonempty_maybe_improper_list, []}, _TypeNames,
- _RecDict, _VarDict) ->
+ _InOpaque, _RecDict, _VarDict) ->
{t_cons(?any, ?any), []};
-t_from_form({type, _L, nonempty_maybe_improper_list, [Cont, Term]}, TypeNames,
- RecDict, VarDict) ->
- {T1, R1} = t_from_form(Cont, TypeNames, RecDict, VarDict),
- {T2, R2} = t_from_form(Term, TypeNames, RecDict, VarDict),
+t_from_form({type, _L, nonempty_maybe_improper_list, [Cont, Term]},
+ TypeNames, InOpaque, RecDict, VarDict) ->
+ {T1, R1} = t_from_form(Cont, TypeNames, InOpaque, RecDict, VarDict),
+ {T2, R2} = t_from_form(Term, TypeNames, InOpaque, RecDict, VarDict),
{t_cons(T1, T2), R1 ++ R2};
-t_from_form({type, _L, nonempty_string, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, nonempty_string, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_nonempty_string(), []};
-t_from_form({type, _L, number, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, number, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_number(), []};
-t_from_form({type, _L, pid, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, pid, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_pid(), []};
-t_from_form({type, _L, port, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, port, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_port(), []};
-t_from_form({type, _L, pos_integer, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_pos_integer(), []};
-t_from_form({type, _L, maybe_improper_list, []}, _TypeNames, _RecDict,
+t_from_form({type, _L, pos_integer, []}, _TypeNames, _InOpaque, _RecDict,
_VarDict) ->
+ {t_pos_integer(), []};
+t_from_form({type, _L, maybe_improper_list, []}, _TypeNames, _InOpaque,
+ _RecDict, _VarDict) ->
{t_maybe_improper_list(), []};
-t_from_form({type, _L, maybe_improper_list, [Content, Termination]}, TypeNames,
- RecDict, VarDict) ->
- {T1, R1} = t_from_form(Content, TypeNames, RecDict, VarDict),
- {T2, R2} = t_from_form(Termination, TypeNames, RecDict, VarDict),
+t_from_form({type, _L, maybe_improper_list, [Content, Termination]},
+ TypeNames, InOpaque, RecDict, VarDict) ->
+ {T1, R1} = t_from_form(Content, TypeNames, InOpaque, RecDict, VarDict),
+ {T2, R2} = t_from_form(Termination, TypeNames, InOpaque, RecDict, VarDict),
{t_maybe_improper_list(T1, T2), R1 ++ R2};
-t_from_form({type, _L, product, Elements}, TypeNames, RecDict, VarDict) ->
- {L, R} = list_from_form(Elements, TypeNames, RecDict, VarDict),
+t_from_form({type, _L, product, Elements}, TypeNames, InOpaque, RecDict,
+ VarDict) ->
+ {L, R} = list_from_form(Elements, TypeNames, InOpaque, RecDict, VarDict),
{t_product(L), R};
-t_from_form({type, _L, queue, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, queue, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_queue(), []};
t_from_form({type, _L, range, [From, To]} = Type,
- _TypeNames, _RecDict, _VarDict) ->
+ _TypeNames, _InOpaque, _RecDict, _VarDict) ->
case {erl_eval:partial_eval(From), erl_eval:partial_eval(To)} of
- {{integer, _, FromVal},
- {integer, _, ToVal}} ->
+ {{integer, _, FromVal}, {integer, _, ToVal}} ->
{t_from_range(FromVal, ToVal), []};
- _ -> throw({error, io_lib:format("Unable evaluate type ~w\n", [Type])})
+ _ -> throw({error, io_lib:format("Unable to evaluate type ~w\n", [Type])})
end;
-t_from_form({type, _L, record, [Name|Fields]}, TypeNames, RecDict, VarDict) ->
- record_from_form(Name, Fields, TypeNames, RecDict, VarDict);
-t_from_form({type, _L, reference, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, record, [Name|Fields]}, TypeNames, InOpaque, RecDict,
+ VarDict) ->
+ record_from_form(Name, Fields, TypeNames, InOpaque, RecDict, VarDict);
+t_from_form({type, _L, reference, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_reference(), []};
-t_from_form({type, _L, set, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, set, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_set(), []};
-t_from_form({type, _L, string, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, string, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_string(), []};
-t_from_form({type, _L, term, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, term, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_any(), []};
-t_from_form({type, _L, tid, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, tid, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_tid(), []};
-t_from_form({type, _L, timeout, []}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, timeout, []}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_timeout(), []};
-t_from_form({type, _L, tuple, any}, _TypeNames, _RecDict, _VarDict) ->
+t_from_form({type, _L, tuple, any}, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{t_tuple(), []};
-t_from_form({type, _L, tuple, Args}, TypeNames, RecDict, VarDict) ->
- {L, R} = list_from_form(Args, TypeNames, RecDict, VarDict),
+t_from_form({type, _L, tuple, Args}, TypeNames, InOpaque, RecDict, VarDict) ->
+ {L, R} = list_from_form(Args, TypeNames, InOpaque, RecDict, VarDict),
{t_tuple(L), R};
-t_from_form({type, _L, union, Args}, TypeNames, RecDict, VarDict) ->
- {L, R} = list_from_form(Args, TypeNames, RecDict, VarDict),
+t_from_form({type, _L, union, Args}, TypeNames, InOpaque, RecDict, VarDict) ->
+ {L, R} = list_from_form(Args, TypeNames, InOpaque, RecDict, VarDict),
{t_sup(L), R};
-t_from_form({type, _L, Name, Args}, TypeNames, RecDict, VarDict) ->
+t_from_form({type, _L, Name, Args}, TypeNames, InOpaque, RecDict, VarDict) ->
case lookup_type(Name, RecDict) of
{type, {_Module, Type, ArgNames}} when length(Args) =:= length(ArgNames) ->
- case unfold({type, Name}, TypeNames) of
+ case can_unfold_more({type, Name}, TypeNames) of
true ->
List = lists:zipwith(
fun(ArgName, ArgType) ->
{Ttemp, _R} = t_from_form(ArgType, TypeNames,
- RecDict, VarDict),
+ InOpaque, RecDict,
+ VarDict),
{ArgName, Ttemp}
end,
ArgNames, Args),
TmpVarDict = dict:from_list(List),
- {T, R} = t_from_form(Type, [{type, Name}|TypeNames], RecDict,
- TmpVarDict),
+ {T, R} = t_from_form(Type, [{type, Name}|TypeNames], InOpaque,
+ RecDict, TmpVarDict),
case lists:member({type, Name}, R) of
true -> {t_limit(T, ?REC_TYPE_LIMIT), R};
false -> {T, R}
@@ -3603,26 +3658,32 @@ t_from_form({type, _L, Name, Args}, TypeNames, RecDict, VarDict) ->
end;
{opaque, {Module, Type, ArgNames}} when length(Args) =:= length(ArgNames) ->
{Rep, Rret} =
- case unfold({opaque, Name}, TypeNames) of
+ case can_unfold_more({opaque, Name}, TypeNames) of
true ->
List = lists:zipwith(
fun(ArgName, ArgType) ->
- {Ttemp, _R} = t_from_form(ArgType, TypeNames,
- RecDict, VarDict),
+ {Ttemp, _R} = t_from_form(ArgType, TypeNames,
+ InOpaque, RecDict,
+ VarDict),
{ArgName, Ttemp}
end,
ArgNames, Args),
TmpVarDict = dict:from_list(List),
- {T, R} = t_from_form(Type, [{opaque, Name}|TypeNames], RecDict,
- TmpVarDict),
+ {T, R} = t_from_form(Type, [{opaque, Name}|TypeNames], true,
+ RecDict, TmpVarDict),
case lists:member({opaque, Name}, R) of
true -> {t_limit(T, ?REC_TYPE_LIMIT), R};
false -> {T, R}
end;
false -> {t_any(), [{opaque, Name}]}
end,
- Tret = t_from_form({opaque, -1, Name, {Module, Args, Rep}},
- RecDict, VarDict),
+ Tret =
+ case InOpaque of
+ true -> Rep;
+ false ->
+ t_from_form({opaque, -1, Name, {Module, Args, Rep}},
+ RecDict, VarDict)
+ end,
{Tret, Rret};
{type, _} ->
throw({error, io_lib:format("Unknown type ~w\n", [Name])});
@@ -3631,15 +3692,16 @@ t_from_form({type, _L, Name, Args}, TypeNames, RecDict, VarDict) ->
error ->
throw({error, io_lib:format("Unable to find type ~w\n", [Name])})
end;
-t_from_form({opaque, _L, Name, {Mod, Args, Rep}}, _TypeNames, _RecDict,
- _VarDict) ->
+t_from_form({opaque, _L, Name, {Mod, Args, Rep}}, _TypeNames, _InOpaque,
+ _RecDict, _VarDict) ->
case Args of
[] -> {t_opaque(Mod, Name, Args, Rep), []};
_ -> throw({error, "Polymorphic opaque types not supported yet"})
end.
-record_from_form({atom, _, Name}, ModFields, TypeNames, RecDict, VarDict) ->
- case unfold({record, Name}, TypeNames) of
+record_from_form({atom, _, Name}, ModFields, TypeNames, InOpaque, RecDict,
+ VarDict) ->
+ case can_unfold_more({record, Name}, TypeNames) of
true ->
case lookup_record(Name, RecDict) of
{ok, DeclFields} ->
@@ -3649,14 +3711,15 @@ record_from_form({atom, _, Name}, ModFields, TypeNames, RecDict, VarDict) ->
{DeclFields1, R1} =
case lists:all(fun(Elem) -> Elem end, AreTyped) of
true -> {DeclFields, []};
- false -> fields_from_form(DeclFields, TypeNames1,
+ false -> fields_from_form(DeclFields, TypeNames1, InOpaque,
RecDict, dict:new())
end,
{GetModRec, R2} = get_mod_record(ModFields, DeclFields1,
- TypeNames1, RecDict, VarDict),
+ TypeNames1, InOpaque,
+ RecDict, VarDict),
case GetModRec of
{error, FieldName} ->
- throw({error, io_lib:format("Illegal declaration of ~w#{~w}\n",
+ throw({error, io_lib:format("Illegal declaration of #~w{~w}\n",
[Name, FieldName])});
{ok, NewFields} ->
{t_tuple(
@@ -3664,17 +3727,18 @@ record_from_form({atom, _, Name}, ModFields, TypeNames, RecDict, VarDict) ->
R1 ++ R2}
end;
error ->
- throw({error, erlang:error(io_lib:format("Unknown record #~w{}\n",
- [Name]))})
+ throw({error, io_lib:format("Unknown record #~w{}\n", [Name])})
end;
false -> {t_any(), []}
end.
-get_mod_record([], DeclFields, _TypeNames, _RecDict, _VarDict) ->
+get_mod_record([], DeclFields, _TypeNames, _InOpaque, _RecDict,
+ _VarDict) ->
{{ok, DeclFields}, []};
-get_mod_record(ModFields, DeclFields, TypeNames, RecDict, VarDict) ->
+get_mod_record(ModFields, DeclFields, TypeNames, InOpaque, RecDict,
+ VarDict) ->
DeclFieldsDict = orddict:from_list(DeclFields),
- {ModFieldsDict, R} = build_field_dict(ModFields, TypeNames,
+ {ModFieldsDict, R} = build_field_dict(ModFields, TypeNames, InOpaque,
RecDict, VarDict),
case get_mod_record(DeclFieldsDict, ModFieldsDict, []) of
{error, _FieldName} = Error -> {Error, R};
@@ -3684,21 +3748,23 @@ get_mod_record(ModFields, DeclFields, TypeNames, RecDict, VarDict) ->
R}
end.
-build_field_dict(FieldTypes, TypeNames, RecDict, VarDict) ->
- build_field_dict(FieldTypes, TypeNames, RecDict, VarDict, []).
+build_field_dict(FieldTypes, TypeNames, InOpaque, RecDict, VarDict) ->
+ build_field_dict(FieldTypes, TypeNames, InOpaque, RecDict, VarDict, []).
build_field_dict([{type, _, field_type, [{atom, _, Name}, Type]}|Left],
- TypeNames, RecDict, VarDict, Acc) ->
- {T, R1} = t_from_form(Type, TypeNames, RecDict, VarDict),
+ TypeNames, InOpaque, RecDict, VarDict, Acc) ->
+ {T, R1} = t_from_form(Type, TypeNames, InOpaque, RecDict, VarDict),
NewAcc = [{Name, T}|Acc],
- {D, R2} = build_field_dict(Left, TypeNames, RecDict, VarDict, NewAcc),
+ {D, R2} = build_field_dict(Left, TypeNames, InOpaque, RecDict, VarDict,
+ NewAcc),
{D, R1 ++ R2};
-build_field_dict([], _TypeNames, _RecDict, _VarDict, Acc) ->
+build_field_dict([], _TypeNames, _InOpaque, _RecDict, _VarDict, Acc) ->
{orddict:from_list(Acc), []}.
get_mod_record([{FieldName, DeclType}|Left1],
[{FieldName, ModType}|Left2], Acc) ->
- case t_is_var(ModType) orelse t_is_subtype(ModType, DeclType) of
+ case t_is_var(ModType) orelse t_is_remote(ModType) orelse
+ t_is_subtype(ModType, DeclType) of
false -> {error, FieldName};
true -> get_mod_record(Left1, Left2, [{FieldName, ModType}|Acc])
end;
@@ -3711,18 +3777,19 @@ get_mod_record(DeclFields, [], Acc) ->
get_mod_record(_, [{FieldName2, _ModType}|_], _Acc) ->
{error, FieldName2}.
-fields_from_form([], _TypeNames, _RecDict, _VarDict) ->
+fields_from_form([], _TypeNames, _InOpaque, _RecDict, _VarDict) ->
{[], []};
-fields_from_form([{Name, Type}|Tail], TypeNames, RecDict, VarDict) ->
- {T, R1} = t_from_form(Type, TypeNames, RecDict, VarDict),
- {F, R2} = fields_from_form(Tail, TypeNames, RecDict, VarDict),
+fields_from_form([{Name, Type}|Tail], TypeNames, InOpaque, RecDict,
+ VarDict) ->
+ {T, R1} = t_from_form(Type, TypeNames, InOpaque, RecDict, VarDict),
+ {F, R2} = fields_from_form(Tail, TypeNames, InOpaque, RecDict, VarDict),
{[{Name, T}|F], R1 ++ R2}.
-list_from_form([], _TypeNames, _RecDict, _VarDict) ->
+list_from_form([], _TypeNames, _InOpaque, _RecDict, _VarDict) ->
{[], []};
-list_from_form([H|Tail], TypeNames, RecDict, VarDict) ->
- {T, R1} = t_from_form(H, TypeNames, RecDict, VarDict),
- {L, R2} = list_from_form(Tail, TypeNames, RecDict, VarDict),
+list_from_form([H|Tail], TypeNames, InOpaque, RecDict, VarDict) ->
+ {T, R1} = t_from_form(H, TypeNames, InOpaque, RecDict, VarDict),
+ {L, R2} = list_from_form(Tail, TypeNames, InOpaque, RecDict, VarDict),
{[T|L], R1 ++ R2}.
-spec t_form_to_string(parse_form()) -> string().
@@ -3881,8 +3948,9 @@ lookup_type(Name, RecDict) ->
type_is_defined(TypeOrOpaque, Name, RecDict) ->
dict:is_key({TypeOrOpaque, Name}, RecDict).
-unfold(TypeName, TypeNames) ->
- not lists:member(TypeName, TypeNames).
+can_unfold_more(TypeName, TypeNames) ->
+ Fun = fun(E, Acc) -> case E of TypeName -> Acc + 1; _ -> Acc end end,
+ lists:foldl(Fun, 0, TypeNames) < ?REC_TYPE_LIMIT.
%% -----------------------------------
%% Set
diff --git a/lib/hipe/doc/src/notes.xml b/lib/hipe/doc/src/notes.xml
index 7b34a4f427..cf30db0482 100644
--- a/lib/hipe/doc/src/notes.xml
+++ b/lib/hipe/doc/src/notes.xml
@@ -30,6 +30,29 @@
</header>
<p>This document describes the changes made to HiPE.</p>
+<section><title>Hipe 3.7.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>The HiPE compiler could crash when compiling certain
+ modules (the bug has been latent, and been exposed by new
+ optimizations introduced in the BEAM compiler in R14A).
+ (Thanks to Mikael Pettersson.)</p>
+ <p>
+ Own Id: OTP-8800</p>
+ </item>
+ <item>
+ <p>
+ hipe:load/1 was broken. (Thanks to Paul Guyot.)</p>
+ <p>
+ Own Id: OTP-8802</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Hipe 3.7.6</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/hipe/icode/hipe_beam_to_icode.erl b/lib/hipe/icode/hipe_beam_to_icode.erl
index 1f8be4040e..920c94d85c 100644
--- a/lib/hipe/icode/hipe_beam_to_icode.erl
+++ b/lib/hipe/icode/hipe_beam_to_icode.erl
@@ -369,6 +369,10 @@ trans_fun([{bif,BifName,{f,Lbl},[_] = Args,Reg}|Instructions], Env) ->
trans_fun([{bif,BifName,{f,Lbl},[_,_] = Args,Reg}|Instructions], Env) ->
{BifInsts,Env1} = trans_bif(2,BifName,Lbl,Args,Reg,Env),
[hipe_icode:mk_comment({bif2,BifName})|BifInsts] ++ trans_fun(Instructions,Env1);
+%%--- bif3 ---
+trans_fun([{bif,BifName,{f,Lbl},[_,_,_] = Args,Reg}|Instructions], Env) ->
+ {BifInsts,Env1} = trans_bif(3,BifName,Lbl,Args,Reg,Env),
+ [hipe_icode:mk_comment({bif3,BifName})|BifInsts] ++ trans_fun(Instructions,Env1);
%%--- allocate
trans_fun([{allocate,StackSlots,_}|Instructions], Env) ->
trans_allocate(StackSlots) ++ trans_fun(Instructions,Env);
diff --git a/lib/hipe/icode/hipe_icode_exceptions.erl b/lib/hipe/icode/hipe_icode_exceptions.erl
index 787fb05415..3c8f7b5712 100644
--- a/lib/hipe/icode/hipe_icode_exceptions.erl
+++ b/lib/hipe/icode/hipe_icode_exceptions.erl
@@ -344,6 +344,16 @@ pop_catch(Cs) ->
pop_catch_1([[_|C] | Cs]) ->
[C | pop_catch_1(Cs)];
+pop_catch_1([[] | Cs]) ->
+ %% The elements in the list represent different possible incoming
+ %% stacks of catch handlers to this BB. Before the fixpoint has
+ %% been found these elements are underapproximations of the true
+ %% stacks, therefore it's possible for these elements to be too
+ %% short for the number of pops implied by the code in the BB.
+ %% We must not fail in that case, so we set pop([]) = [].
+ %% This fixes find_catches_crash.erl and compiler_tests in the
+ %% HiPE test suite.
+ [[] | pop_catch_1(Cs)];
pop_catch_1([]) ->
[].
diff --git a/lib/hipe/icode/hipe_icode_type.erl b/lib/hipe/icode/hipe_icode_type.erl
index 28198467f7..3f9488d7c3 100644
--- a/lib/hipe/icode/hipe_icode_type.erl
+++ b/lib/hipe/icode/hipe_icode_type.erl
@@ -2,19 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
-%%
+%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
%%%--------------------------------------------------------------------
@@ -23,8 +23,6 @@
%%% Description : Propagate type information.
%%%
%%% Created : 25 Feb 2003 by Tobias Lindahl <[email protected]>
-%%%
-%%% $Id$
%%%--------------------------------------------------------------------
-module(hipe_icode_type).
@@ -78,7 +76,7 @@
%-define(server_debug, fun(X, Y) -> io:format("~p server: ~s ~p~n", [self(), X, Y]) end).
-define(server_debug, fun(_, _) -> ok end).
--import(erl_types, [min/2, max/2, number_min/1, number_max/1,
+-import(erl_types, [number_min/1, number_max/1,
t_any/0, t_atom/1, t_atom/0, t_atom_vals/1,
t_binary/0, t_bitstr/0, t_bitstr_base/1, t_bitstr_unit/1,
t_boolean/0, t_cons/0, t_constant/0,
@@ -494,10 +492,10 @@ integer_range_less_then_propagator(IntArg1, IntArg2) ->
Min2 = number_min(IntArg2),
Max2 = number_max(IntArg2),
%% is this the same as erl_types:t_subtract?? no ... ??
- TrueMax1 = min(Max1, erl_bif_types:infinity_add(Max2, -1)),
- TrueMin2 = max(erl_bif_types:infinity_add(Min1, 1), Min2),
- FalseMin1 = max(Min1, Min2),
- FalseMax2 = min(Max1, Max2),
+ TrueMax1 = erl_types:min(Max1, erl_bif_types:infinity_add(Max2, -1)),
+ TrueMin2 = erl_types:max(erl_bif_types:infinity_add(Min1, 1), Min2),
+ FalseMin1 = erl_types:max(Min1, Min2),
+ FalseMax2 = erl_types:min(Max1, Max2),
{t_from_range(Min1, TrueMax1),
t_from_range(TrueMin2, Max2),
t_from_range(FalseMin1, Max1),
diff --git a/lib/hipe/main/hipe.erl b/lib/hipe/main/hipe.erl
index ed722fecba..c80fb6a0a2 100644
--- a/lib/hipe/main/hipe.erl
+++ b/lib/hipe/main/hipe.erl
@@ -274,7 +274,7 @@ load(Mod, BeamFileName) when is_list(BeamFileName) ->
Architecture = erlang:system_info(hipe_architecture),
ChunkName = hipe_unified_loader:chunk_name(Architecture),
case beam_lib:chunks(BeamFileName, [ChunkName]) of
- {ok,{_,[{_,Bin}]}} when is_binary(Bin) -> do_load(Mod, Bin, Bin);
+ {ok,{_,[{_,Bin}]}} when is_binary(Bin) -> do_load(Mod, Bin, BeamFileName);
Error -> {error, Error}
end.
@@ -913,7 +913,7 @@ do_load(Mod, Bin, WholeModule) ->
%% In this case, the emulated code for the module must be loaded.
{module, Mod} = code:ensure_loaded(Mod),
code:load_native_partial(Mod, Bin);
- BinCode when is_binary(BinCode) ->
+ BeamBinOrPath when is_binary(BeamBinOrPath) orelse is_list(BeamBinOrPath) ->
case code:is_sticky(Mod) of
true ->
%% We unpack and repack the Beam binary as a workaround to
diff --git a/lib/hipe/regalloc/hipe_graph_coloring_regalloc.erl b/lib/hipe/regalloc/hipe_graph_coloring_regalloc.erl
index ac555b933c..ce33af453a 100644
--- a/lib/hipe/regalloc/hipe_graph_coloring_regalloc.erl
+++ b/lib/hipe/regalloc/hipe_graph_coloring_regalloc.erl
@@ -389,23 +389,23 @@ decrement_each([N|Ns], OldLow, IG, Vis, K) ->
%% {Spilled_node, Low_degree_neighbors, New_interference_graph}
spill(IG, Vis, Spill, K, SpillLimit, Target) ->
- Ns = list_ig(IG),
- Costs = spill_costs(Ns, IG, Vis, Spill, SpillLimit, Target),
- ?report3("spill costs are ~p~n",[Costs]),
- ActualCosts = lists:sort(Costs),
- ?report3("actual costs are ~p~n",[ActualCosts]),
+ Ns = list_ig(IG),
+ Costs = spill_costs(Ns, IG, Vis, Spill, SpillLimit, Target),
+ ?report3("spill costs are ~p~n", [Costs]),
+ ActualCosts = lists:sort(Costs),
+ ?report3("actual costs are ~p~n", [ActualCosts]),
case ActualCosts of
- [] ->
- ?error_msg("There is no node to spill",[]),
+ [] ->
+ ?error_msg("There is no node to spill", []),
?EXIT('no node to spill');
[{_Cost,N}|_] ->
{Low, NewIG} = decrement_neighbors(N, [], IG, Vis, K),
- %?report("spilled node ~p at cost ~p (~p now ready)~n",[N,Cost,Low]),
+ %% ?report("spilled node ~p at cost ~p (~p now ready)~n", [N,Cost,Low]),
{N, Low, NewIG}
end.
spill_costs([], _IG, _Vis, _Spill, _SpillLimit, _Target) ->
- [];
+ [];
spill_costs([{N,Info}|Ns], IG, Vis, Spill, SpillLimit, Target) ->
case degree(Info) of
0 -> spill_costs(Ns,IG,Vis,Spill, SpillLimit, Target);
@@ -451,28 +451,28 @@ select_colors([{X,colorable}|Xs], IG, Cols, PhysRegs, K) ->
{Reg,NewCols} = select_color(X, IG, Cols, PhysRegs),
?report("~p~n",[Reg]),
[{X,{reg,Reg}} | select_colors(Xs, IG, NewCols, PhysRegs, K)];
-%select_colors([{X,{spill,M}}|Xs], IG, Cols, PhysRegs, K) ->
-% ?report('spilled: ~p~n',[X]),
-% %% Check if optimistic coloring could have found a color
-% case catch select_color(X,IG,Cols,K) of
-% {'EXIT',_} -> % no color possible
-% ?report('(no optimistic color)~n',[]),
-% [{X,{spill,M}}|select_colors(Xs, IG, Cols, PhysRegs, K)];
-% {Reg,NewCols} ->
-% ?report('(optimistic color: ~p)~n',[Reg]),
-% [{X,{reg,Reg}}|select_colors(Xs, IG, Cols, PhysRegs, K)]
-% end.
+%%select_colors([{X,{spill,M}}|Xs], IG, Cols, PhysRegs, K) ->
+%% ?report('spilled: ~p~n',[X]),
+%% %% Check if optimistic coloring could have found a color
+%% case catch select_color(X,IG,Cols,K) of
+%% {'EXIT',_} -> % no color possible
+%% ?report('(no optimistic color)~n',[]),
+%% [{X,{spill,M}}|select_colors(Xs, IG, Cols, PhysRegs, K)];
+%% {Reg,NewCols} ->
+%% ?report('(optimistic color: ~p)~n',[Reg]),
+%% [{X,{reg,Reg}}|select_colors(Xs, IG, Cols, PhysRegs, K)]
+%% end.
%% Old code / pessimistic coloring:
select_colors([{X,{spill,M}}|Xs], IG, Cols, PhysRegs, K) ->
?report("spilled: ~p~n",[X]),
%% Check if optimistic coloring could have found a color
-% case catch select_color(X,IG,Cols,K) of
-% {'EXIT',_} -> % no color possible
-% ?report('(no optimistic color)~n',[]);
-% {Reg,NewCols} ->
-% ?report('(optimistic color: ~p)~n',[Reg])
-% end,
+%% case catch select_color(X,IG,Cols,K) of
+%% {'EXIT',_} -> % no color possible
+%% ?report('(no optimistic color)~n',[]);
+%% {Reg,NewCols} ->
+%% ?report('(optimistic color: ~p)~n',[Reg])
+%% end,
[{X,{spill,M}} | select_colors(Xs, IG, Cols, PhysRegs, K)].
select_color(X, IG, Cols, PhysRegs) ->
diff --git a/lib/hipe/vsn.mk b/lib/hipe/vsn.mk
index 31c860ddec..8e421ce9b2 100644
--- a/lib/hipe/vsn.mk
+++ b/lib/hipe/vsn.mk
@@ -1 +1 @@
-HIPE_VSN = 3.7.6
+HIPE_VSN = 3.7.7
diff --git a/lib/hipe/x86/hipe_x86_spill_restore.erl b/lib/hipe/x86/hipe_x86_spill_restore.erl
index e60c446e17..cd927669fb 100644
--- a/lib/hipe/x86/hipe_x86_spill_restore.erl
+++ b/lib/hipe/x86/hipe_x86_spill_restore.erl
@@ -1,20 +1,20 @@
%% -*- erlang-indent-level: 2 -*-
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
%% ====================================================================
@@ -71,9 +71,9 @@ firstPass(Defun) ->
case hipe_x86_cfg:reverse_postorder(CFG0) of
[Label1, Label2|_] ->
SaveTreeElement = saveTreeLookup(Label2, SaveTree),
- %% FilteredSaveTreeElement is the to be spilled temps around the function call.
- %% They are spilled just before move formals
- FilteredSaveTreeElement = [Temp || Temp <- SaveTreeElement, temp_is_pseudo(Temp)],
+ %% FilteredSaveTreeElement is the to be spilled temps around the
+ %% function call. They are spilled just before move formals.
+ FilteredSaveTreeElement = [T || T <- SaveTreeElement, temp_is_pseudo(T)],
Block = hipe_x86_cfg:bb(CFG1, Label1),
Code = hipe_bb:code(Block),
%% The following statements are tedious but work ok.
@@ -83,7 +83,7 @@ firstPass(Defun) ->
%% Another solution may be to introduce another block.
MoveCodes = lists:sublist(Code, length(Code)-1),
JumpCode = lists:last(Code),
- hipe_x86_cfg:bb_add(CFG1, Label1, hipe_bb:mk_bb(MoveCodes ++ [hipe_x86:mk_pseudo_spill(FilteredSaveTreeElement)] ++ [JumpCode]));
+ hipe_x86_cfg:bb_add(CFG1, Label1, hipe_bb:mk_bb(MoveCodes ++ [hipe_x86:mk_pseudo_spill(FilteredSaveTreeElement), JumpCode]));
_ ->
CFG1
end.
@@ -110,13 +110,12 @@ firstPassHelper([Label|Labels], Liveness, CFG, SaveTree) ->
NewBlock = hipe_bb:code_update(Block, NewCode),
NewCFG = hipe_x86_cfg:bb_add(CFG, Label, NewBlock),
SizeOfSet = setSize(NewIntersectedList),
-
%% if the Intersected Save List is not empty, insert it in the save tree.
if SizeOfSet =/= 0 ->
- UpdatedSaveTree = gb_trees:insert(Label,NewIntersectedList,SaveTree),
- firstPassHelper(Labels, Liveness, NewCFG,UpdatedSaveTree);
+ UpdatedSaveTree = gb_trees:insert(Label, NewIntersectedList, SaveTree),
+ firstPassHelper(Labels, Liveness, NewCFG, UpdatedSaveTree);
true ->
- firstPassHelper(Labels, Liveness, NewCFG,SaveTree)
+ firstPassHelper(Labels, Liveness, NewCFG, SaveTree)
end;
firstPassHelper([], _, CFG, SaveTree) ->
{CFG, SaveTree}.
@@ -125,17 +124,15 @@ firstPassHelper([], _, CFG, SaveTree) ->
firstPassDoBlock(Insts, LiveOut, IntersectedSaveList) ->
lists:foldr(fun firstPassDoInsn/2, {LiveOut,IntersectedSaveList,[]}, Insts).
-firstPassDoInsn(I, {LiveOut,IntersectedSaveList,PrevInsts} ) ->
+firstPassDoInsn(I, {LiveOut,IntersectedSaveList,PrevInsts}) ->
case I of
#pseudo_call{} ->
do_pseudo_call(I, {LiveOut,IntersectedSaveList,PrevInsts});
_ -> % other instructions
DefinedList = from_list( ?HIPE_X86_LIVENESS:defines(I)),
UsedList = from_list(?HIPE_X86_LIVENESS:uses(I)),
-
NewLiveOut = subtract(union(LiveOut, UsedList), DefinedList),
- NewIntersectedSaveList = subtract(IntersectedSaveList, DefinedList),
-
+ NewIntersectedSaveList = subtract(IntersectedSaveList, DefinedList),
{NewLiveOut, NewIntersectedSaveList, [I|PrevInsts]}
end.
@@ -162,7 +159,7 @@ saveTreeLookup(Label, SaveTree) ->
[]
end.
-%% Performs the second pass of the algoritm.
+%% Performs the second pass of the algorithm.
%% It basically eliminates the unnecessary spills and introduces restores.
%% Works top down
secondPass(CFG0) ->
@@ -306,7 +303,8 @@ addRestoreBlockToEdge(PseudoCall, ContLabel, CFG, TempArgsList) ->
NewCFG = hipe_x86_cfg:bb_add(CFG, NextLabel, NewBlock),
{NewCFG, NewPseudoCall}.
-%% used instead of hipe_x86_cfg:redirect_jmp since it does not handle pseudo_call calls.
+%% used instead of hipe_x86_cfg:redirect_jmp since it does not handle
+%% pseudo_call calls.
redirect_pseudo_call(I = #pseudo_call{contlab=ContLabel}, Old, New) ->
case Old =:= ContLabel of
true -> I#pseudo_call{contlab=New};
@@ -323,8 +321,8 @@ temp_is_pseudo(Temp) ->
%% Set operations where the module name is an easily changeable macro
%%---------------------------------------------------------------------
-union(Set1,Set2) ->
- ?SET_MODULE:union(Set1,Set2).
+union(Set1, Set2) ->
+ ?SET_MODULE:union(Set1, Set2).
setSize(Set) ->
?SET_MODULE:size(Set).
diff --git a/lib/ic/test/Makefile b/lib/ic/test/Makefile
new file mode 100644
index 0000000000..1142159d19
--- /dev/null
+++ b/lib/ic/test/Makefile
@@ -0,0 +1,277 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 1998-2010. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+#
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../vsn.mk
+VSN=$(IC_VSN)
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/ic_test
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+TEST_SPEC_FILE = ic.spec ic.spec.vxworks
+
+
+IDL_FILES =
+
+COMPILER_TEST_FILES = \
+ ic_SUITE_data/Corba.idl \
+ ic_SUITE_data/Coss.idl \
+ ic_SUITE_data/attr.idl \
+ ic_SUITE_data/c_err1.idl \
+ ic_SUITE_data/c_err2.idl \
+ ic_SUITE_data/c_err3.idl \
+ ic_SUITE_data/c_norm.idl \
+ ic_SUITE_data/enum.idl \
+ ic_SUITE_data/forward.idl \
+ ic_SUITE_data/include.idl \
+ ic_SUITE_data/include2.idl \
+ ic_SUITE_data/include3.idl \
+ ic_SUITE_data/inherit.idl \
+ ic_SUITE_data/inherit_err.idl \
+ ic_SUITE_data/inherit_warn.idl \
+ ic_SUITE_data/mult_ids.idl \
+ ic_SUITE_data/nasty.idl \
+ ic_SUITE_data/one.idl \
+ ic_SUITE_data/one_out.idl \
+ ic_SUITE_data/one_raises.idl \
+ ic_SUITE_data/one_followed.idl \
+ ic_SUITE_data/one_void.idl \
+ ic_SUITE_data/raises_reg.idl \
+ ic_SUITE_data/struct.idl \
+ ic_SUITE_data/syntax1.idl \
+ ic_SUITE_data/syntax2.idl \
+ ic_SUITE_data/syntax3.idl \
+ ic_SUITE_data/syntax4.idl \
+ ic_SUITE_data/syntax5.idl \
+ ic_SUITE_data/syntax6.idl \
+ ic_SUITE_data/type.idl \
+ ic_SUITE_data/typeid.idl \
+ ic_SUITE_data/u_case_mult.idl \
+ ic_SUITE_data/u_mult.idl \
+ ic_SUITE_data/u_norm.idl \
+ ic_SUITE_data/u_type.idl \
+ ic_SUITE_data/u_default.idl \
+ ic_SUITE_data/undef_id.idl
+
+
+COMPILER_TEST_FILES2 = \
+ ic_register_SUITE_data/reg_m8.idl \
+ ic_register_SUITE_data/reg_m9.idl \
+ ic_register_SUITE_data/reg_m10.idl \
+ ic_register_SUITE_data/reg_m11.idl \
+ ic_register_SUITE_data/reg_m12.idl
+
+
+COMPILER_TEST_FILES3 = \
+ ic_pragma_SUITE_data/reg_m0.idl \
+ ic_pragma_SUITE_data/reg_m1.idl \
+ ic_pragma_SUITE_data/reg_m2.idl \
+ ic_pragma_SUITE_data/reg_m3.idl \
+ ic_pragma_SUITE_data/reg_m4.idl \
+ ic_pragma_SUITE_data/reg_m5.idl \
+ ic_pragma_SUITE_data/reg_m6.idl \
+ ic_pragma_SUITE_data/reg_m7.idl \
+ ic_pragma_SUITE_data/uggly.idl
+
+
+COMPILER_TEST_FILES4 = \
+ ic_be_SUITE_data/plain.idl
+
+
+PREPROCESSOR_TEST_FILES = \
+ ic_pp_SUITE_data/arg.idl \
+ ic_pp_SUITE_data/cascade.idl \
+ ic_pp_SUITE_data/comment.idl \
+ ic_pp_SUITE_data/concat.idl \
+ ic_pp_SUITE_data/define.idl \
+ ic_pp_SUITE_data/if.idl \
+ ic_pp_SUITE_data/if_zero.idl \
+ ic_pp_SUITE_data/improp_nest_constr.idl \
+ ic_pp_SUITE_data/inc.idl \
+ ic_pp_SUITE_data/line.idl \
+ ic_pp_SUITE_data/misc.idl \
+ ic_pp_SUITE_data/nopara.idl \
+ ic_pp_SUITE_data/predef.idl \
+ ic_pp_SUITE_data/predef_time.idl \
+ ic_pp_SUITE_data/self_ref.idl \
+ ic_pp_SUITE_data/separate.idl \
+ ic_pp_SUITE_data/swallow_sc.idl \
+ ic_pp_SUITE_data/unintended_grp.idl
+
+C_CLIENT_ERL_SERVER_TEST_FILES = \
+ c_client_erl_server_SUITE_data/Makefile.src \
+ c_client_erl_server_SUITE_data/c_erl_test.idl \
+ c_client_erl_server_SUITE_data/c_client.c \
+ c_client_erl_server_SUITE_data/m_i_impl.erl
+
+C_CLIENT_ERL_SERVER_PROTO_TEST_FILES = \
+ c_client_erl_server_proto_SUITE_data/Makefile.src \
+ c_client_erl_server_proto_SUITE_data/c_erl_test.idl \
+ c_client_erl_server_proto_SUITE_data/c_client.c \
+ c_client_erl_server_proto_SUITE_data/my.c \
+ c_client_erl_server_proto_SUITE_data/m_i_impl.erl
+
+C_CLIENT_ERL_SERVER_PROTO_TMO_TEST_FILES = \
+ c_client_erl_server_proto_tmo_SUITE_data/Makefile.src \
+ c_client_erl_server_proto_tmo_SUITE_data/c_erl_test.idl \
+ c_client_erl_server_proto_tmo_SUITE_data/c_client.c \
+ c_client_erl_server_proto_tmo_SUITE_data/my.c \
+ c_client_erl_server_proto_tmo_SUITE_data/m_i_impl.erl
+
+ERL_CLIENT_C_SERVER_TEST_FILES = \
+ erl_client_c_server_SUITE_data/Makefile.src \
+ erl_client_c_server_SUITE_data/erl_c_test.idl \
+ erl_client_c_server_SUITE_data/erl_client.erl \
+ erl_client_c_server_SUITE_data/c_server.c \
+ erl_client_c_server_SUITE_data/callbacks.c
+
+ERL_CLIENT_C_SERVER_PROTO_TEST_FILES = \
+ erl_client_c_server_proto_SUITE_data/Makefile.src \
+ erl_client_c_server_proto_SUITE_data/erl_c_test.idl \
+ erl_client_c_server_proto_SUITE_data/erl_client.erl \
+ erl_client_c_server_proto_SUITE_data/c_server.c \
+ erl_client_c_server_proto_SUITE_data/callbacks.c
+
+JAVA_CLIENT_ERL_SERVER_TEST_FILES = \
+ java_client_erl_server_SUITE_data/Makefile.src \
+ java_client_erl_server_SUITE_data/java_erl_test.idl \
+ java_client_erl_server_SUITE_data/JavaClient.java \
+ java_client_erl_server_SUITE_data/m_i_impl.erl
+
+MODULES = \
+ ic_SUITE \
+ ic_register_SUITE \
+ ic_pragma_SUITE \
+ ic_pp_SUITE \
+ ic_be_SUITE \
+ c_client_erl_server_SUITE \
+ c_client_erl_server_proto_SUITE \
+ c_client_erl_server_proto_tmo_SUITE \
+ erl_client_c_server_SUITE \
+ erl_client_c_server_proto_SUITE \
+ java_client_erl_server_SUITE
+
+GEN_MODULES =
+
+ERL_FILES = $(MODULES:%=%.erl)
+
+HRL_FILES =
+
+GEN_HRL_FILES =
+
+
+GEN_FILES = \
+ $(GEN_HRL_FILES:%=$(IDLOUTDIR)/%) \
+ $(GEN_MODULES=:%=$(IDLOUTDIR)/%.erl)
+
+GEN_TARGET_FILES = $(GEN_MODULES:%=$(IDLOUTDIR)/%.$(EMULATOR))
+
+SUITE_TARGET_FILES = $(MODULES:%=%.$(EMULATOR))
+
+TARGET_FILES = \
+ $(GEN_TARGET_FILES) \
+ $(SUITE_TARGET_FILES)
+
+# ----------------------------------------------------
+# PROGRAMS
+# ----------------------------------------------------
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+ERL_LOCAL_FLAGS += -pa $(ERL_TOP)/lib/orber/ebin -pa $(ERL_TOP)/lib/ic/ebin
+
+ERL_COMPILE_FLAGS += \
+ $(ERL_LOCAL_FLAGS) \
+ -pa $(ERL_TOP)/lib/test_server/ebin \
+ -pa $(ERL_TOP)/lib/orber/ebin \
+ -I$(ERL_TOP)/lib/orber \
+ -I$(ERL_TOP)/lib/test_server/include
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+tests debug opt: $(TARGET_FILES)
+
+clean:
+ rm -f $(TARGET_FILES)
+ rm -f errs core *~
+
+docs:
+
+# ----------------------------------------------------
+# Special Targets
+# ----------------------------------------------------
+
+
+# ----------------------------------------------------
+# Release Targets
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_spec:
+
+release_docs_spec:
+
+release_tests_spec: tests
+ $(INSTALL_DIR) $(RELSYSDIR)
+ $(INSTALL_DIR) $(RELSYSDIR)/ic_SUITE_data
+ $(INSTALL_DIR) $(RELSYSDIR)/ic_register_SUITE_data
+ $(INSTALL_DIR) $(RELSYSDIR)/ic_pragma_SUITE_data
+ $(INSTALL_DIR) $(RELSYSDIR)/ic_pp_SUITE_data
+ $(INSTALL_DIR) $(RELSYSDIR)/ic_be_SUITE_data
+ $(INSTALL_DIR) $(RELSYSDIR)/c_client_erl_server_SUITE_data
+ $(INSTALL_DIR) $(RELSYSDIR)/c_client_erl_server_proto_SUITE_data
+ $(INSTALL_DIR) $(RELSYSDIR)/c_client_erl_server_proto_tmo_SUITE_data
+ $(INSTALL_DIR) $(RELSYSDIR)/erl_client_c_server_SUITE_data
+ $(INSTALL_DIR) $(RELSYSDIR)/erl_client_c_server_proto_SUITE_data
+ $(INSTALL_DIR) $(RELSYSDIR)/java_client_erl_server_SUITE_data
+ $(INSTALL_DATA) $(IDL_FILES) $(TEST_SPEC_FILE) $(ERL_FILES) \
+ $(RELSYSDIR)
+ $(INSTALL_DATA) $(COMPILER_TEST_FILES) $(RELSYSDIR)/ic_SUITE_data
+ $(INSTALL_DATA) $(COMPILER_TEST_FILES2) \
+ $(RELSYSDIR)/ic_register_SUITE_data
+ $(INSTALL_DATA) $(COMPILER_TEST_FILES3) \
+ $(RELSYSDIR)/ic_pragma_SUITE_data
+ $(INSTALL_DATA) $(COMPILER_TEST_FILES4) \
+ $(RELSYSDIR)/ic_be_SUITE_data
+ $(INSTALL_DATA) $(PREPROCESSOR_TEST_FILES) \
+ $(RELSYSDIR)/ic_pp_SUITE_data
+ $(INSTALL_DATA) $(C_CLIENT_ERL_SERVER_TEST_FILES) \
+ $(RELSYSDIR)/c_client_erl_server_SUITE_data
+ $(INSTALL_DATA) $(C_CLIENT_ERL_SERVER_PROTO_TEST_FILES) \
+ $(RELSYSDIR)/c_client_erl_server_proto_SUITE_data
+ $(INSTALL_DATA) $(C_CLIENT_ERL_SERVER_PROTO_TMO_TEST_FILES) \
+ $(RELSYSDIR)/c_client_erl_server_proto_tmo_SUITE_data
+ $(INSTALL_DATA) $(ERL_CLIENT_C_SERVER_TEST_FILES) \
+ $(RELSYSDIR)/erl_client_c_server_SUITE_data
+ $(INSTALL_DATA) $(ERL_CLIENT_C_SERVER_PROTO_TEST_FILES) \
+ $(RELSYSDIR)/erl_client_c_server_proto_SUITE_data
+ $(INSTALL_DATA) $(SUITE_TARGET_FILES) $(RELSYSDIR)
+ $(INSTALL_DATA) $(JAVA_CLIENT_ERL_SERVER_TEST_FILES) \
+ $(RELSYSDIR)/java_client_erl_server_SUITE_data
diff --git a/lib/ic/test/c_client_erl_server_SUITE.erl b/lib/ic/test/c_client_erl_server_SUITE.erl
new file mode 100644
index 0000000000..40c1395d10
--- /dev/null
+++ b/lib/ic/test/c_client_erl_server_SUITE.erl
@@ -0,0 +1,315 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+
+%%----------------------------------------------------------------------
+%% Purpose : Test suite for c-client/erl-server
+%%----------------------------------------------------------------------
+
+
+-module(c_client_erl_server_SUITE).
+-include("test_server.hrl").
+
+-export([init_per_testcase/2, fin_per_testcase/2,
+ all/1, void_test/1, long_test/1, long_long_test/1,
+ unsigned_short_test/1, unsigned_long_test/1,
+ unsigned_long_long_test/1, double_test/1, char_test/1,
+ wchar_test/1, octet_test/1, bool_test/1, struct_test/1,
+ struct2_test/1, seq1_test/1, seq2_test/1, seq3_test/1,
+ seq4_test/1, seq5_test/1, array1_test/1, array2_test/1,
+ enum_test/1, string1_test/1, string2_test/1, string3_test/1,
+ string4_test/1, pid_test/1, port_test/1, ref_test/1, term_test/1,
+ typedef_test/1, inline_sequence_test/1, term_sequence_test/1,
+ term_struct_test/1, wstring1_test/1]).
+
+-define(DEFAULT_TIMEOUT, 20000).
+-define(PORT_TIMEOUT, 15000).
+-define(ERLANG_SERVER_NAME, idl_erlang_server).
+-define(C_CLIENT_NODE_NAME, c_client_idl_test).
+
+%% Add/remove code path and watchdog before/after each test case.
+%%
+init_per_testcase(_Case, Config) ->
+ DataDir = ?config(data_dir, Config),
+ code:add_patha(DataDir),
+
+ %% Since other test suites use the module m_i, we have
+ %% to make sure we are using the right m_i module.
+ code:purge(m_i),
+ code:load_file(m_i),
+
+ WatchDog = test_server:timetrap(?DEFAULT_TIMEOUT),
+ [{watchdog, WatchDog}| Config].
+
+fin_per_testcase(_Case, Config) ->
+ DataDir = ?config(data_dir, Config),
+ code:del_path(DataDir),
+ WatchDog = ?config(watchdog, Config),
+ test_server:timetrap_cancel(WatchDog).
+
+all(doc) ->
+ "Test of IC with a C-client and an Erlang generic server. "
+ "The communication is via Erlang distribution.";
+all(suite) ->
+ [void_test, long_test, long_long_test, unsigned_short_test,
+ unsigned_long_test, unsigned_long_long_test, double_test,
+ char_test, wchar_test, octet_test, bool_test, struct_test,
+ struct2_test, seq1_test, seq2_test, seq3_test, seq4_test,
+ seq5_test, array1_test, array2_test, enum_test, string1_test,
+ string2_test, string3_test, string4_test, pid_test, port_test,
+ ref_test, term_test, typedef_test, inline_sequence_test,
+ term_sequence_test, term_struct_test, wstring1_test].
+
+
+array1_test(doc) -> "";
+array1_test(suite) -> [];
+array1_test(Config) ->
+ do_test(array1_test, Config).
+
+array2_test(doc) -> "";
+array2_test(suite) -> [];
+array2_test(Config) ->
+ do_test(array2_test, Config).
+
+bool_test(doc) -> "";
+bool_test(suite) -> [];
+bool_test(Config) ->
+ do_test(bool_test, Config).
+
+char_test(doc) -> "";
+char_test(suite) -> [];
+char_test(Config) ->
+ do_test(char_test, Config).
+
+double_test(doc) -> "";
+double_test(suite) -> [];
+double_test(Config) ->
+ do_test(double_test, Config).
+
+enum_test(doc) -> "";
+enum_test(suite) -> [];
+enum_test(Config) ->
+ do_test(enum_test, Config).
+
+inline_sequence_test(doc) -> "";
+inline_sequence_test(suite) -> [];
+inline_sequence_test(Config) ->
+ do_test(inline_sequence_test, Config).
+
+long_long_test(doc) -> "";
+long_long_test(suite) -> [];
+long_long_test(Config) ->
+ do_test(long_long_test, Config).
+
+long_test(doc) -> "";
+long_test(suite) -> [];
+long_test(Config) ->
+ do_test(long_test, Config).
+
+octet_test(doc) -> "";
+octet_test(suite) -> [];
+octet_test(Config) ->
+ do_test(octet_test, Config).
+
+pid_test(doc) -> "";
+pid_test(suite) -> [];
+pid_test(Config) ->
+ do_test(pid_test, Config).
+
+port_test(doc) -> "";
+port_test(suite) -> [];
+port_test(Config) ->
+ do_test(port_test, Config).
+
+ref_test(doc) -> "";
+ref_test(suite) -> [];
+ref_test(Config) ->
+ do_test(ref_test, Config).
+
+seq1_test(doc) -> "";
+seq1_test(suite) -> [];
+seq1_test(Config) ->
+ do_test(seq1_test, Config).
+
+seq2_test(doc) -> "";
+seq2_test(suite) -> [];
+seq2_test(Config) ->
+ do_test(seq2_test, Config).
+
+seq3_test(doc) -> "";
+seq3_test(suite) -> [];
+seq3_test(Config) ->
+ do_test(seq3_test, Config).
+
+seq4_test(doc) -> "";
+seq4_test(suite) -> [];
+seq4_test(Config) ->
+ do_test(seq4_test, Config).
+
+seq5_test(doc) -> "";
+seq5_test(suite) -> [];
+seq5_test(Config) ->
+ do_test(seq5_test, Config).
+
+string1_test(doc) -> "";
+string1_test(suite) -> [];
+string1_test(Config) ->
+ do_test(string1_test, Config).
+
+string2_test(doc) -> "";
+string2_test(suite) -> [];
+string2_test(Config) ->
+ do_test(string2_test, Config).
+
+string3_test(doc) -> "";
+string3_test(suite) -> [];
+string3_test(Config) ->
+ do_test(string3_test, Config).
+
+string4_test(doc) -> "";
+string4_test(suite) -> [];
+string4_test(Config) ->
+ do_test(string4_test, Config).
+
+struct2_test(doc) -> "";
+struct2_test(suite) -> [];
+struct2_test(Config) ->
+ do_test(struct2_test, Config).
+
+struct_test(doc) -> "";
+struct_test(suite) -> [];
+struct_test(Config) ->
+ do_test(struct_test, Config).
+
+term_sequence_test(doc) -> "";
+term_sequence_test(suite) -> [];
+term_sequence_test(Config) ->
+ do_test(term_sequence_test, Config).
+
+term_struct_test(doc) -> "";
+term_struct_test(suite) -> [];
+term_struct_test(Config) ->
+ do_test(term_struct_test, Config).
+
+term_test(doc) -> "";
+term_test(suite) -> [];
+term_test(Config) ->
+ do_test(term_test, Config).
+
+typedef_test(doc) -> "";
+typedef_test(suite) -> [];
+typedef_test(Config) ->
+ do_test(typedef_test, Config).
+
+unsigned_long_long_test(doc) -> "";
+unsigned_long_long_test(suite) -> [];
+unsigned_long_long_test(Config) ->
+ do_test(unsigned_long_long_test, Config).
+
+unsigned_long_test(doc) -> "";
+unsigned_long_test(suite) -> [];
+unsigned_long_test(Config) ->
+ do_test(unsigned_long_test, Config).
+
+unsigned_short_test(doc) -> "";
+unsigned_short_test(suite) -> [];
+unsigned_short_test(Config) ->
+ do_test(unsigned_short_test, Config).
+
+void_test(doc) -> "";
+void_test(suite) -> [];
+void_test(Config) ->
+ do_test(void_test, Config).
+
+wchar_test(doc) -> "";
+wchar_test(suite) -> [];
+wchar_test(Config) ->
+ do_test(wchar_test, Config).
+
+wstring1_test(doc) -> "";
+wstring1_test(suite) -> [];
+wstring1_test(Config) ->
+ do_test(wstring1_test, Config).
+
+
+%% It is here that all tests really are done.
+%%
+
+do_test(Case, Config) ->
+ %% Trap exits
+ process_flag(trap_exit, true),
+ %% Start the server
+ {ok, _Pid} = m_i:oe_create_link([], {local, ?ERLANG_SERVER_NAME}),
+ Node = atom_to_list(node()),
+ DataDir = ?config(data_dir, Config),
+ %% io:format("~p: data directory: ~p~n", [?MODULE, DataDir]),
+ Cookie = atom_to_list(erlang:get_cookie()),
+ %% Start C-client node as a port program.
+ Cmd = filename:join([DataDir, "c_client"]) ++
+ " -this-node-name " ++ atom_to_list(?C_CLIENT_NODE_NAME) ++
+ " -peer-node " ++ Node ++
+ " -peer-process-name " ++ atom_to_list(?ERLANG_SERVER_NAME) ++
+ " -cookie " ++ Cookie ++
+ " -test-case " ++ atom_to_list(Case),
+ Port = open_port({spawn, Cmd}, [exit_status, eof, stderr_to_stdout]),
+ Res = wait_for_completion(Port),
+ %% Kill off node if there was timeout
+ case Res of
+ {error, timeout} ->
+ catch rpc:cast(?C_CLIENT_NODE_NAME, erlang, halt, [1]);
+ _ ->
+ ok
+ end,
+ process_flag(trap_exit, false),
+ catch m_i:stop(?ERLANG_SERVER_NAME),
+ ok = Res.
+
+
+%% Wait for eof *and* exit status, but return if exit status indicates
+%% an error, or we have been waiting more than PORT_TIMEOUT seconds.
+%%
+wait_for_completion(Port) ->
+ wait_for_completion(Port, 0).
+
+wait_for_completion(Port, N) when N < 2 ->
+ receive
+ {Port, {data, Bytes}} ->
+ %% Relay output
+ io:format("~s", [Bytes]),
+ wait_for_completion(Port, N);
+ {Port, {exit_status, 0}} ->
+ wait_for_completion(Port, N + 1);
+ {Port, {exit_status, Status}} ->
+ {error, Status};
+ {Port, eof} ->
+ wait_for_completion(Port, N + 1);
+ {'EXIT', Port, Reason} ->
+ io:format("Port exited with reason: ~w~n", [Reason]),
+ wait_for_completion(Port, N);
+ {'EXIT', From, Reason} ->
+ io:format("Got unexpected exit: ~p~n", [{'EXIT', From, Reason}]),
+ wait_for_completion(Port, N)
+ after ?PORT_TIMEOUT ->
+ {error, timeout}
+ end;
+wait_for_completion(_, _) ->
+ ok.
+
+
+
diff --git a/lib/ic/test/c_client_erl_server_SUITE_data/Makefile.src b/lib/ic/test/c_client_erl_server_SUITE_data/Makefile.src
new file mode 100644
index 0000000000..6516e699bd
--- /dev/null
+++ b/lib/ic/test/c_client_erl_server_SUITE_data/Makefile.src
@@ -0,0 +1,145 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2001-2009. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+#
+# Makefile.src for c_client_erl_server test
+# Note: This file *must* work for both Unix and Windows
+#
+# We use both `rm' (Unix) and `del' (Windows) for removing files, but
+# with a `-' in front so that the error in not finding `rm' (`del') on
+# Windows (Unix) is ignored.
+#
+# VxWorks? XXX
+#
+
+.SUFFIXES:
+.SUFFIXES: .c .h .erl .idl @obj@ .@EMULATOR@
+
+
+# Variables from ts:
+#
+
+ERL_INCLUDE = @erl_include@
+
+IC_INCLUDE_PATH = @ic_include_path@
+IC_LIB = @ic_libpath@@DS@@ic_lib@
+
+ERL_INTERFACE_INCLUDE = @erl_interface_include@
+ERL_INTERFACE_LIB = @erl_interface_libpath@@DS@@erl_interface_lib@
+ERL_INTERFACE_EILIB = @erl_interface_libpath@@DS@@erl_interface_eilib@
+ERL_INTERFACE_THREADLIB = @erl_interface_threadlib@
+ERL_INTERFACE_SOCK_LIBS = @erl_interface_sock_libs@
+
+CC = @CC@
+## XXX Should set warning flag with a DEBUG_FLAG
+CFLAGS = @CFLAGS@ @DEFS@ -I@erl_include@ \
+ -I@ic_include_path@ -I@erl_interface_include@
+
+LD = @LD@
+LDFLAGS = @CROSSLDFLAGS@
+LIBS = $(IC_LIB) $(ERL_INTERFACE_LIB) $(ERL_INTERFACE_EILIB) \
+ $(ERL_INTERFACE_THREADLIB) @LIBS@ $(ERL_INTERFACE_SOCK_LIBS)
+ERLC = erlc
+
+# Generated C header files
+GEN_H_FILES = \
+ m.h \
+ m_i.h \
+ oe_c_erl_test.h
+
+# Generated C files
+GEN_C_FILES = \
+ m.c \
+ m_i.c \
+ oe_c_erl_test.c \
+ oe_code_m_a.c \
+ oe_code_m_arr1.c \
+ oe_code_m_arr2.c \
+ oe_code_m_arr3.c \
+ oe_code_m_aseq.c \
+ oe_code_m_b.c \
+ oe_code_m_bseq.c \
+ oe_code_m_dd.c \
+ oe_code_m_dyn.c \
+ oe_code_m_dyn_sl.c \
+ oe_code_m_es.c \
+ oe_code_m_et.c \
+ oe_code_m_etseq.c \
+ oe_code_m_fruit.c \
+ oe_code_m_lseq.c \
+ oe_code_m_s.c \
+ oe_code_m_s_sl.c \
+ oe_code_m_sarr3.c \
+ oe_code_m_simple.c \
+ oe_code_m_ssarr3.c \
+ oe_code_m_sseq.c \
+ oe_code_m_ssstr3.c \
+ oe_code_m_sstr3.c \
+ oe_code_m_str1.c \
+ oe_code_m_str3.c \
+ oe_code_m_strRec.c \
+ oe_code_m_strRec_str5.c \
+ oe_code_m_strRec_str7.c
+
+GEN_HRL_FILES = \
+ m.hrl \
+ m_i.hrl \
+ oe_c_erl_test.hrl
+
+GEN_ERL_FILES = \
+ m.erl \
+ m_arr2.erl \
+ m_arr3.erl \
+ m_i.erl \
+ m_str3.erl \
+ oe_c_erl_test.erl
+
+C_FILES = $(GEN_C_FILES) c_client.c
+
+OBJS = $(C_FILES:.c=@obj@)
+
+PGMS = c_client@exe@
+
+ERL_FILES = $(GEN_ERL_FILES) m_i_impl.erl
+
+EBINS = $(ERL_FILES:.erl=.@EMULATOR@)
+
+
+all: $(PGMS) $(EBINS)
+
+clean:
+ -rm -f $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \
+ $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES)
+ -del /F /Q $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \
+ $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES)
+
+$(PGMS): $(OBJS)
+ $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
+
+$(GEN_C_FILES) $(GEN_H_FILES): c_erl_test.idl
+ $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,c_client}" c_erl_test.idl
+
+$(GEN_ERL_FILES) $(GEN_HRL_FILES): c_erl_test.idl
+ $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,erl_genserv}" c_erl_test.idl
+
+.c@obj@:
+ $(CC) -c -o $*@obj@ $(CFLAGS) $<
+
+.erl.@EMULATOR@:
+ $(ERLC) -I $(IC_INCLUDE_PATH) $<
+
diff --git a/lib/ic/test/c_client_erl_server_SUITE_data/c_client.c b/lib/ic/test/c_client_erl_server_SUITE_data/c_client.c
new file mode 100644
index 0000000000..e4f9cfdece
--- /dev/null
+++ b/lib/ic/test/c_client_erl_server_SUITE_data/c_client.c
@@ -0,0 +1,1760 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2001-2010. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+ */
+/* C-client for test of IC.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef __WIN32__
+# include <unistd.h>
+#endif
+
+#include <string.h>
+
+#ifdef __WIN32__
+# include <time.h>
+# include <sys/timeb.h>
+#elif defined VXWORKS
+#include <time.h>
+#include <sys/times.h>
+#else
+#include <sys/time.h>
+#endif
+
+#include <ctype.h>
+
+#ifdef __WIN32__
+# include <winsock2.h>
+# include <windows.h>
+#else
+# include <sys/types.h>
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <arpa/inet.h>
+# include <netdb.h>
+#endif
+
+#include "ei.h"
+#include "erl_interface.h"
+#include "m_i.h"
+
+#define HOSTNAMESZ 256
+#define NODENAMESZ 512
+
+#define INBUFSZ 10
+#define OUTBUFSZ 0
+
+#define MAXTRIES 5
+
+#define CHECK_EXCEPTION(x) \
+ if ((x)->_major != CORBA_NO_EXCEPTION) { \
+ fprintf(stderr,"\n\nException: %s\n\n", \
+ (char *)CORBA_exception_value((x))); \
+ CORBA_exception_free((x)); \
+ return -1; \
+ } \
+
+/* XXX Should free things here too! */
+#define RETURN_IF_OK(x) \
+ if ((x)) {\
+ fprintf(stdout, "ok\n");\
+ return 0;\
+ }\
+
+#define cmp_str(x,y) (!strcmp((x),(y)))
+#define cmp_wstr(x,y) (!ic_wstrcmp((x),(y)))
+
+typedef CORBA_Environment IC_Env;
+
+typedef int (*TestFunc)(IC_Env *);
+typedef struct {
+ char *name;
+ TestFunc func;
+} TestCase;
+
+static char longtext[] =
+"Introduction The IC application is an IDL compiler implemented in Erlang."
+" The IDL compiler generates client stubs and server skeletons."
+" Several back-ends are supported, and they fall into three main groups."
+" For more details on IC compiler options consult the ic(3) manual page."
+" Argument passing cases 1 Caller allocates all necessary storage,"
+" except that which may be encapsulated and managed within the parameter itself."
+" 2 The caller allocates a pointer and passes it by reference to the callee."
+" The callee sets the pointer to point to a valid instance of the parameter's type."
+" The caller is responsible for releasing the returned storage."
+" Following completion of a request, the caller is not allowed to modify any values"
+" in the returned storage. To do so the caller must first copy the returned instance"
+" into a new instance, then modify the new instance. 3 The caller allocates a"
+" pointer to an array slice which has all the same dimensions of the original"
+" array except the first, and passes it by reference to the callee. The callee sets"
+" the pointer to point to a valid instance of the array. The caller is responsible for"
+" releasing the returned storage. Following completion of a request, the caller is not"
+" allowed to modify any values in the returned storage. To do so the caller must first"
+" copy the returned instance into a new instance, then modify the new instance."
+" Generated Files Two files will be generated for each scope. One set of files will be"
+" generated for each module and each interface scope. An extra set is generated for"
+" those definitions at top level scope. One of the files is a header file(.h), and the"
+" other file is a C source code file (.c). In addition to these files a number of C"
+" source files will be generated for type encodings, they are named according to the "
+"following template: oe_code_<type>.c.";
+static char this_node[NODENAMESZ + 1];
+static char *progname;
+
+/* Test function prototypes */
+
+static int void_test(IC_Env *env);
+static int long_test(IC_Env *env);
+static int long_long_test(IC_Env *env);
+static int unsigned_short_test(IC_Env *env);
+static int unsigned_long_test(IC_Env *env);
+static int unsigned_long_long_test(IC_Env *env);
+static int double_test(IC_Env *env);
+static int char_test(IC_Env *env);
+static int wchar_test(IC_Env *env);
+static int octet_test(IC_Env *env);
+static int bool_test(IC_Env *env);
+static int struct_test(IC_Env *env);
+static int struct2_test(IC_Env *env);
+static int seq1_test(IC_Env *env);
+static int seq2_test(IC_Env *env);
+static int seq3_test(IC_Env *env);
+static int seq4_test(IC_Env *env);
+static int seq5_test(IC_Env *env);
+static int array1_test(IC_Env *env);
+static int array2_test(IC_Env *env);
+static int enum_test(IC_Env *env);
+static int string1_test(IC_Env *env);
+static int string2_test(IC_Env *env);
+static int string3_test(IC_Env *env);
+static int string4_test(IC_Env *env);
+static int pid_test(IC_Env *env);
+static int port_test(IC_Env *env);
+static int ref_test(IC_Env *env);
+static int term_test(IC_Env *env);
+static int typedef_test(IC_Env *env);
+static int inline_sequence_test(IC_Env *env);
+static int term_sequence_test(IC_Env *env);
+static int term_struct_test(IC_Env *env);
+static int wstring1_test(IC_Env *env);
+
+static TestCase test_cases[] = {
+ {"void_test", void_test},
+ {"long_test", long_test},
+ {"long_long_test", long_long_test},
+ {"unsigned_short_test", unsigned_short_test},
+ {"unsigned_long_test", unsigned_long_test},
+ {"unsigned_long_long_test", unsigned_long_long_test},
+ {"double_test", double_test},
+ {"char_test", char_test},
+ {"wchar_test", wchar_test},
+ {"octet_test", octet_test},
+ {"bool_test", bool_test},
+ {"struct_test", struct_test},
+ {"struct2_test", struct2_test},
+ {"seq1_test", seq1_test},
+ {"seq2_test", seq2_test},
+ {"seq3_test", seq3_test},
+ {"seq4_test", seq4_test},
+ {"seq5_test", seq5_test},
+ {"array1_test", array1_test},
+ {"array2_test", array2_test},
+ {"enum_test", enum_test},
+ {"string1_test", string1_test},
+ {"string2_test", string2_test},
+ {"string3_test", string3_test},
+ {"string4_test", string4_test},
+ {"pid_test", pid_test},
+ {"port_test", port_test},
+ {"ref_test", ref_test},
+ {"term_test", term_test},
+ {"typedef_test", typedef_test},
+ {"inline_sequence_test", inline_sequence_test},
+ {"term_sequence_test", term_sequence_test},
+ {"term_struct_test", term_struct_test},
+ {"wstring1_test", wstring1_test},
+ {"", NULL}
+};
+
+/* Other prototypes */
+static int cmp_aseq(m_aseq *a1, m_aseq *a2);
+static int cmp_a(m_a *a1, m_a *a2);
+static int cmp_bseq(m_bseq *b1, m_bseq *b2);
+static int cmp_b(m_b *b1, m_b *b2);
+static int cmp_lseq(m_lseq *b1, m_lseq *b2);
+static int cmp_etseq(m_etseq *b1, m_etseq *b2);
+static int cmp_et(m_et* b1, m_et *b2);
+static int cmp_es(m_es *b1, m_es *b2);
+static int cmp_arr1(m_arr1 b1, m_arr1 b2);
+static int cmp_dd(m_dd b1, m_dd b2);
+static int cmp_strRec(m_strRec *b1, m_strRec *b2);
+static int cmp_sseq(m_sseq *b1, m_sseq *b2);
+static int cmp_pid(erlang_pid *p1, erlang_pid *p2);
+static int cmp_port(erlang_port *p1, erlang_port *p2);
+static int cmp_ref(erlang_ref *p1, erlang_ref *p2);
+static int cmp_s(m_s *b1, m_s *b2);
+static int cmp_ssstr3(m_ssstr3 *b1, m_ssstr3 *b2);
+static int cmp_ssarr3(m_ssarr3 *b1, m_ssarr3 *b2);
+static int cmp_sarr3(m_sarr3 *b1, m_sarr3 *b2);
+static int cmp_arr3(m_arr3 b1, m_arr3 b2);
+
+static void print_aseq(m_aseq *a);
+static void print_a(m_a *a);
+static void print_bseq(m_bseq *b);
+static void print_lseq(m_lseq *b);
+static void print_b(m_b *b);
+static void print_etseq(m_etseq *b);
+static void print_et(m_et* b);
+static void print_es(m_es *b);
+static void print_arr1(long a[500]);
+static void print_dd(long a[2][3]);
+static void print_strRec(m_strRec* sr);
+static void print_sseq(m_sseq *b);
+static void print_pid(erlang_pid *p);
+static void print_port(erlang_port *p);
+static void print_ref(erlang_ref *p);
+static void print_term(ETERM *t);
+static void print_s(m_s *p);
+static void print_ssstr3(m_ssstr3 *b1);
+static void print_ssarr3(m_ssarr3 *b1);
+static void print_sarr3(m_sarr3 *b1);
+static void print_arr3(m_arr3 b1);
+static void print_wstr(CORBA_wchar *ws);
+
+static void free_etseq_buf(m_etseq *b);
+static void free_et(m_et* b);
+
+#ifdef __WIN32__
+typedef struct {
+ long tv_sec;
+ long tv_usec;
+} MyTimeval;
+#else
+typedef struct timeval MyTimeval;
+#endif
+static void my_gettimeofday(MyTimeval *tv);
+static void showtime(MyTimeval *start, MyTimeval *stop);
+static void usage(void);
+static void done(int r);
+
+
+
+/* main */
+
+#ifdef VXWORKS
+int client(int argc, char **argv)
+#else
+int main(int argc, char **argv)
+#endif
+{
+ struct hostent *hp;
+ erlang_pid pid;
+ MyTimeval start, stop;
+ int i, fd, ires, tres;
+ IC_Env *env;
+ int tries = 0;
+ char *this_node_name = NULL;
+ char *peer_node = NULL;
+ char *peer_process_name = NULL;
+ char *cookie = NULL;
+ char host[HOSTNAMESZ + 1];
+ TestFunc test_func = NULL;
+ TestCase *test_case;
+ char *test_case_name = NULL;
+
+#ifdef __WIN32__
+ WORD wVersionRequested;
+ WSADATA wsaData;
+
+ wVersionRequested = MAKEWORD(2, 0);
+
+ if (WSAStartup(wVersionRequested, &wsaData) != 0) {
+ fprintf(stderr, "Could not load winsock2 v2.0 compatible DLL");
+ exit(1);
+ }
+#endif
+
+ progname = argv[0];
+ host[HOSTNAMESZ] = '\0';
+ if (gethostname(host, HOSTNAMESZ) < 0) {
+ fprintf(stderr, "Can't find own hostname\n");
+ done(1);
+ }
+ if ((hp = gethostbyname(host)) == 0) {
+ fprintf(stderr, "Can't get ip address for host %s\n", host);
+ done(1);
+ }
+ for (i = 1; i < argc; i++) {
+ if (cmp_str(argv[i], "-help")) {
+ usage();
+ done(0);
+ } else if (cmp_str(argv[i], "-this-node-name")) {
+ i++;
+ this_node_name = argv[i];
+ } else if (cmp_str(argv[i], "-peer-node")) {
+ i++;
+ peer_node = argv[i];
+ } else if (cmp_str(argv[i], "-peer-process-name")) {
+ i++;
+ peer_process_name = argv[i];
+ } else if (cmp_str(argv[i], "-cookie")) {
+ i++;
+ cookie = argv[i];
+ } else if (cmp_str(argv[i], "-test-case")) {
+ i++;
+ test_case_name = argv[i];
+ } else {
+ fprintf(stderr, "Error : invalid argument \"%s\"\n", argv[i]);
+ usage();
+ done(1);
+ }
+ }
+
+ if (this_node_name == NULL || peer_node == NULL || test_case_name == NULL
+ || peer_process_name == NULL || cookie == NULL) {
+ fprintf(stderr, "Error: missing option\n");
+ usage();
+ done(1);
+ }
+
+ test_case = test_cases;
+ while (test_case->func) {
+ if (cmp_str(test_case->name, test_case_name)) {
+ test_func = test_case->func;
+ break;
+ }
+ test_case++;
+ }
+ if (test_func == NULL) {
+ fprintf(stderr, "Error: illegal test case: \"%s\"\n", test_case_name);
+ done(1);
+ }
+
+ /* Behead hostname at first dot */
+ for (i=0; host[i] != '\0'; i++) {
+ if (host[i] == '.') { host[i] = '\0'; break; }
+ }
+ sprintf(this_node, "%s@%s", this_node_name, host);
+ fprintf(stderr, "c_client: this node: \"%s\"\n", this_node);
+ fprintf(stderr, "c_client: peer node: \"%s\"\n", peer_node);
+ fprintf(stderr, "c_client: test case: \"%s\"\n", test_case_name);
+
+ fprintf(stderr, "c_client: starting\n");
+
+ /* initialize erl_interface */
+ erl_init(NULL, 0);
+
+ for (tries = 0; tries < MAXTRIES; tries++) {
+
+ /* connect to erlang node */
+
+ ires = erl_connect_xinit(host, this_node_name, this_node,
+ (struct in_addr *)*hp->h_addr_list,
+ cookie, 0);
+
+ fprintf(stderr, "c_client: erl_connect_xinit(): %d\n", ires);
+
+ fd = erl_connect(peer_node);
+ fprintf(stderr, "c_client: erl_connect(): %d\n", fd);
+
+ if (fd >= 0)
+ break;
+ fprintf(stderr, "c_client: cannot connect, retrying\n");
+ }
+ if (fd < 0) {
+ fprintf(stderr, "c_client: cannot connect, exiting\n");
+ done(1);
+ }
+ env = CORBA_Environment_alloc(INBUFSZ, OUTBUFSZ);
+ env->_fd = fd;
+ strcpy(env->_regname, peer_process_name);
+ env->_to_pid = NULL;
+ env->_from_pid = &pid;
+
+ strcpy(pid.node, this_node);
+ pid.num = fd;
+ pid.serial = 0;
+ pid.creation = 0;
+
+ my_gettimeofday(&start);
+ tres = test_func(env); /* Call test case */
+ my_gettimeofday(&stop);
+ showtime(&start, &stop);
+ erl_close_connection(fd);
+
+ printf("c_client: env->_inbuf before : %d\n", INBUFSZ);
+ printf("c_client: env->_outbuf before : %d\n", OUTBUFSZ);
+ printf("c_client: env->_inbuf after : %d\n", env->_inbufsz);
+ printf("c_client: env->_outbuf after : %d\n", env->_outbufsz);
+
+ CORBA_free(env->_inbuf);
+ CORBA_free(env->_outbuf);
+ CORBA_free(env);
+ done(tres);
+}
+
+static void usage()
+{
+ fprintf(stderr, "Usage: %s [-help] -this-node-name <name> "
+ "-peer-node <nodename> -peer-process-name <name> "
+ "-cookie <cookie> -test-case <test case name>\n", progname);
+ fprintf(stderr, "Example:\n %s -this-node-name kalle "
+ "-peer-node olle@home -peer-process-name idltest "
+ "-cookie oa678er -test-case octet_test\n", progname);
+}
+
+static void done(int r)
+{
+#ifdef __WIN32__
+ WSACleanup();
+#endif
+ exit(r);
+}
+
+
+/* TESTS */
+
+static int void_test(IC_Env *env)
+{
+ fprintf(stdout, "\n======== m_i_void test ======\n\n");
+ m_i_void_test(NULL,env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(1);
+}
+
+static int long_test(IC_Env *env)
+{
+ long l = 4711, lo, lr;
+
+ fprintf(stdout, "\n======== m_i_long test ======\n\n");
+ lr = m_i_long_test(NULL, l, &lo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(l == lo && l == lr);
+ if (l != lo)
+ fprintf(stdout, " out parameter error, sent: %ld, got: %ld\n", l, lo);
+ if (l != lr)
+ fprintf(stdout, " result error, sent: %ld, got: %ld\n", l, lr);
+ return -1;
+}
+
+static int long_long_test(IC_Env *env)
+{
+ CORBA_long_long ll = 4711, llo, llr;
+
+ fprintf(stdout, "\n======== m_i_longlong test ======\n\n");
+ llr = m_i_longlong_test(NULL, ll, &llo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(ll == llo && ll == llr);
+ if (ll != llo)
+ fprintf(stdout, " out parameter error, sent: %ld, got: %ld\n",
+ ll, llo);
+ if (ll != llr)
+ fprintf(stdout, " result error, sent: %ld, got: %ld\n", ll, llr);
+ return -1;
+}
+
+static int unsigned_short_test(IC_Env *env)
+{
+ unsigned short x, y = 2, z;
+
+ fprintf(stdout, "\n======== m_i_ushort test ======\n\n");
+ x = m_i_ushort_test(NULL, y, &z, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(y == z && y == x);
+ if (y != z)
+ fprintf(stdout, " out parameter error, sent: %d, got: %d\n", y, z);
+ if (y != x)
+ fprintf(stdout, " result error, sent: %d, got: %d\n", y, x);
+ return -1;
+}
+
+
+static int unsigned_long_test(IC_Env *env)
+{
+ unsigned long ul = 5050, ulo, ulr;
+
+ fprintf(stdout, "\n======== m_i_ulong test ======\n\n");
+ ulr = m_i_ulong_test(NULL, ul, &ulo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(ul == ulo && ul == ulr);
+ if (ul != ulo)
+ fprintf(stdout, " out parameter error, sent: %lu, got: %lu\n",
+ ul, ulo);
+ if (ul != ulr)
+ fprintf(stdout, " result error, sent: %lu, got: %lu\n", ul, ulr);
+ return -1;
+}
+
+/*
+ * Note: CORBA_unsigned_long_long is in fact a plain long.
+ */
+static int unsigned_long_long_test(IC_Env *env)
+{
+ CORBA_unsigned_long_long ull = 5050, ullo, ullr;
+
+ fprintf(stdout, "\n======== m_i_ulonglong test ======\n\n");
+ ullr = m_i_ulonglong_test(NULL, ull, &ullo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(ull == ullo && ull == ullr);
+ if (ull != ullo)
+ fprintf(stdout, " out parameter error, sent: %lu, got: %lu\n",
+ ull, ullo);
+ if (ull != ullr)
+ fprintf(stdout, " result error, sent: %lu, got: %lu\n",
+ ull, ullr);
+ return -1;
+}
+
+static int double_test(IC_Env *env)
+{
+ double d = 12.1212, db, dr;
+
+ fprintf(stdout, "\n======== m_i_double test ======\n\n");
+ dr = m_i_double_test(NULL, d, &db, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(d == db && d == dr);
+ if (d != db)
+ fprintf(stdout, " out parameter error, sent: %f, got: %f\n", d, db);
+ if (d != dr)
+ fprintf(stdout, " result error, sent: %f, got: %f\n", d, dr);
+ return -1;
+}
+
+static int char_test(IC_Env *env)
+{
+ char c = 'g', co, cr;
+
+ /* char test */
+ fprintf(stdout, "\n======== m_i_char test ======\n\n");
+ cr = m_i_char_test(NULL, c, &co, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(c == co && c == cr);
+ if (c !=co)
+ fprintf(stdout, " out parameter error, sent: %c, got: %c\n", c, co);
+ if (c != cr)
+ fprintf(stdout, " result error, sent: %c, got: %c\n", c, cr);
+ return -1;
+}
+
+static int wchar_test(IC_Env *env)
+{
+ CORBA_wchar wc = 103, wco, wcr;
+
+ fprintf(stdout, "\n======== m_i_wchar test ======\n\n");
+ wcr = m_i_wchar_test(NULL, wc, &wco, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(wc == wco && wc == wcr);
+ if (wc != wco)
+ fprintf(stdout, " out parameter error, sent: %lu, got: %lu\n",
+ wc, wco);
+ if (wc != wcr)
+ fprintf(stdout, " result error, sent: %lu, got: %lu\n",
+ wc, wcr);
+ return -1;
+}
+
+static int octet_test(IC_Env *env)
+{
+ char o ='r', oo, or;
+
+ fprintf(stdout, "\n======== m_i_octet test ======\n\n");
+ or = m_i_octet_test(NULL, o, &oo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(o == oo && o == or);
+ if (o != oo)
+ fprintf(stdout, " out parameter error, sent: %c, got: %c\n", o, oo);
+ if (o != or)
+ fprintf(stdout, " result error, sent: %c, got: %c\n", o, or);
+ return -1;
+}
+
+static int bool_test(IC_Env *env)
+{
+ unsigned char i = 0, io, ir;
+
+ fprintf(stdout, "\n======== m_i_bool test ======\n\n");
+ ir = m_i_bool_test(NULL, i, &io, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(i == io && i == ir);
+ if (i != io)
+ fprintf(stdout, " out parameter error, sent: %d, got: %d\n", i, io);
+ if (i != ir)
+ fprintf(stdout, " result error, sent: %d, got: %d\n", i, ir);
+ return -1;
+}
+
+static int struct_test(IC_Env *env)
+{
+ m_b b = {4711, 'a'}, bo, br;
+
+ fprintf(stdout, "\n======== m_i_struct test ======\n\n");
+ br = m_i_struct_test(NULL, &b, &bo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_b(&b, &bo) && cmp_b(&b, &br));
+ if (!cmp_b(&b, &bo)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_b(&b);
+ fprintf(stdout, " got:\n");
+ print_b(&bo);
+ fprintf(stdout, "\n");
+ }
+ if (!cmp_b(&b, &br)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_b(&b);
+ fprintf(stdout, " got:\n");
+ print_b(&br);
+ fprintf(stdout, "\n");
+ }
+ return -1;
+}
+
+static int struct2_test(IC_Env *env)
+{
+ m_es esi = {m_peach, 5050}, eso, esr;
+
+ fprintf(stdout, "\n======== m_i_struct2 test ======\n\n");
+ esr = m_i_struct2_test(NULL, &esi, &eso, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_es(&esi, &eso) && cmp_es(&esi, &esr));
+ if (!cmp_es(&esi, &eso)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_es(&esi);
+ fprintf(stdout, " got:\n");
+ print_es(&eso);
+ fprintf(stdout, "\n");
+ }
+ if (!cmp_es(&esi, &esr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_es(&esi);
+ fprintf(stdout, " got:\n");
+ print_es(&esr);
+ fprintf(stdout, "\n");
+ }
+ return -1;
+}
+
+
+static int seq1_test(IC_Env *env)
+{
+ m_bseq bs, *bso, *bsr;
+
+ m_b ba[3] = {{4711, 'a'}, {4712, 'b'}, {4713, 'c'}};
+ bs._length = 3;
+ bs._buffer = ba;
+
+ fprintf(stdout, "\n======== m_i_seq1 test ======\n\n");
+ bsr = m_i_seq1_test(NULL, &bs, &bso, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_bseq(&bs, bso) && cmp_bseq(&bs, bsr));
+ if (!cmp_bseq(&bs, bso)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_bseq(&bs);
+ fprintf(stdout, " got:\n");
+ print_bseq(bso);
+ fprintf(stdout, "\n");
+ }
+ if (!cmp_bseq(&bs, bsr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_bseq(&bs);
+ fprintf(stdout, " got:\n");
+ print_bseq(bsr);
+ fprintf(stdout, "\n");
+ }
+ CORBA_free(bso);
+ CORBA_free(bsr);
+ return -1;
+}
+
+static int seq2_test(IC_Env *env)
+{
+ m_b ba[3] = {{4711, 'a'}, {4712, 'b'}, {4713, 'c'}};
+ m_a a;
+ m_a aa[2];
+ m_aseq as, *aso, *asr;
+
+ a.l = 9999;
+ a.y._length = 3;
+ a.y._buffer = ba;
+ a.d = 66.89898989;
+
+ aa[0] = a;
+ aa[1] = a;
+ as._length = 2;
+ as._buffer = aa;
+
+ fprintf(stdout, "\n======== m_i_seq2 test ======\n\n");
+ asr = m_i_seq2_test(NULL, &as, &aso, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_aseq(&as, aso) && cmp_aseq(&as, asr));
+ if (!cmp_aseq(&as, aso)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_aseq(&as);
+ fprintf(stdout, " got:\n");
+ print_aseq(aso);
+ fprintf(stdout, "\n");
+ }
+ if (!cmp_aseq(&as, asr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_aseq(&as);
+ fprintf(stdout, " got:\n");
+ print_aseq(asr);
+ fprintf(stdout, "\n");
+ }
+ CORBA_free(aso);
+ CORBA_free(asr);
+ return -1;
+}
+
+static int seq3_test(IC_Env *env)
+{
+ m_lseq lsi, *lso, *lsr;
+ long al[500];
+ int i=0;
+
+ for (i = 0; i < 500; i++)
+ al[i]=i;
+ lsi._length = 500;
+ lsi._buffer = al;
+
+ fprintf(stdout, "\n======== m_i_seq3 test ======\n\n");
+ lsr = m_i_seq3_test(NULL, &lsi, &lso, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_lseq(&lsi, lso) && cmp_lseq(&lsi, lsr));
+ if (!cmp_lseq(&lsi, lso)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_lseq(&lsi);
+ fprintf(stdout, " got:\n");
+ print_lseq(lso);
+ fprintf(stdout, "\n");
+ }
+ if (!cmp_lseq(&lsi, lsr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_lseq(&lsi);
+ fprintf(stdout, " got:\n");
+ print_lseq(lsr);
+ fprintf(stdout, "\n");
+ }
+ CORBA_free(lso);
+ CORBA_free(lsr);
+ return -1;
+}
+
+static int seq4_test(IC_Env *env)
+{
+ char *stra0[3] = {"a", "long", "time"};
+ char *stra1[3] = {"ago", "there", "was"};
+ char *stra2[3] = {"a", "buggy", "compiler"};
+ m_sstr3 str3s[3] = {{3, 3, stra0}, {3, 3, stra1}, {3, 3, stra2}};
+ m_ssstr3 str3ssi = {3, 3, str3s};
+ m_ssstr3 *str3sso, *str3ssr;
+
+ fprintf(stdout, "\n======== m_i_seq4 test ======\n\n");
+ str3ssr = m_i_seq4_test(NULL, &str3ssi, &str3sso, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_ssstr3(&str3ssi, str3sso) &&
+ cmp_ssstr3(&str3ssi, str3ssr));
+ if (!cmp_ssstr3(&str3ssi, str3sso)){
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_ssstr3(&str3ssi);
+ fprintf(stdout, " got:\n");
+ print_ssstr3(str3sso);
+ fprintf(stdout, "\n");
+ }
+ if (!cmp_ssstr3(&str3ssi, str3ssr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_ssstr3(&str3ssi);
+ fprintf(stdout, " got:\n");
+ print_ssstr3(str3ssr);
+ fprintf(stdout, "\n");
+ }
+ CORBA_free(str3sso);
+ CORBA_free(str3ssr);
+ return -1;
+}
+
+static int seq5_test(IC_Env *env)
+{
+ m_arr3 arr3a[3] = {
+ {4711, 18931947, 3},
+ {4711, 18931947, 3},
+ {4711, 18931947, 3}};
+ m_sarr3 arr3sa[3] = {{3, 3, arr3a}, {3, 3, arr3a}, {3, 3, arr3a}};
+ m_ssarr3 arr3ssi = {3, 3, arr3sa};
+ m_ssarr3 *arr3sso;
+ m_ssarr3 *arr3ssr;
+
+ fprintf(stdout, "\n======== m_i_seq5 test ======\n\n");
+ arr3ssr = m_i_seq5_test(NULL, &arr3ssi, &arr3sso, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_ssarr3(&arr3ssi, arr3sso) &&
+ cmp_ssarr3(&arr3ssi, arr3ssr));
+ if (!cmp_ssarr3(&arr3ssi, arr3sso)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_ssarr3(&arr3ssi);
+ fprintf(stdout, " got:\n");
+ print_ssarr3(arr3sso);
+ fprintf(stdout, "\n");
+ }
+ if (!cmp_ssarr3(&arr3ssi, arr3ssr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_ssarr3(&arr3ssi);
+ fprintf(stdout, " got:\n");
+ print_ssarr3(arr3ssr);
+ fprintf(stdout, "\n");
+ }
+ CORBA_free(arr3sso);
+ CORBA_free(arr3ssr);
+ return -1;
+}
+
+static int array1_test(IC_Env *env)
+{
+ int i;
+ long al[500];
+ m_arr1 alo;
+ m_arr1_slice* alr;
+
+ for (i = 0; i < 500; i++)
+ al[i]=i;
+
+ fprintf(stdout, "\n======== m_i_array1 test ======\n\n");
+ alr = m_i_array1_test(NULL, al, alo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_arr1(al, alo) && cmp_arr1(al, alr));
+ if (!cmp_arr1(al, alo)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_arr1(al);
+ fprintf(stdout, " got:\n");
+ print_arr1(alo);
+ fprintf(stdout, "\n");
+ }
+ if (!cmp_arr1(al,alr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_arr1(al);
+ fprintf(stdout, " got:\n");
+ print_arr1(alr);
+ fprintf(stdout, "\n");
+ }
+ free(alo);
+ free(alr);
+ return -1;
+}
+
+static int array2_test(IC_Env *env)
+{
+ long dl[2][3] = {{11, 2, 7}, {22, 8 ,13}};
+ m_dd dlo;
+ m_dd_slice* dlr;
+
+ fprintf(stdout, "\n======== m_i_array2 test ======\n\n");
+ dlr = m_i_array2_test(NULL, dl, dlo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_dd(dl,dlo) && cmp_dd(dl,dlr));
+ if (!cmp_dd(dl,dlo)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_dd(dl);
+ fprintf(stdout, " got:\n");
+ print_dd(dlo);
+ fprintf(stdout, "\n");
+ }
+ if (!cmp_dd(dl,dlr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_dd(dl);
+ fprintf(stdout, " got:\n");
+ print_dd(dlr);
+ fprintf(stdout, "\n");
+ }
+ free(*dlr);
+ return -1;
+}
+
+static int enum_test(IC_Env *env)
+{
+ m_fruit ei = m_banana, eo, er;
+
+ fprintf(stdout, "\n======== m_i_enum test ======\n\n");
+ er = m_i_enum_test(NULL, ei, &eo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(ei == eo && ei == er);
+ if (ei != eo)
+ fprintf(stdout, " out parameter error, sent: %d, got: %d\n", ei, eo);
+ if (ei != er)
+ fprintf(stdout, " result error, sent: %d, got: %d\n", ei, er);
+ return -1;
+}
+
+static int string1_test(IC_Env *env)
+{
+ char* si = longtext;
+ char* so;
+ char* sr;
+
+ fprintf(stdout, "\n======== m_i_string1 test ======\n\n");
+ sr = m_i_string1_test(NULL, si, &so, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_str(si, so) && cmp_str(si, sr));
+ if (!cmp_str(si, so))
+ fprintf(stdout, " out parameter error, sent: %s, got: %s\n", si, so);
+ if (!cmp_str(si, sr))
+ fprintf(stdout, " result error, sent: %s, got: %s\n", si, sr);
+ CORBA_free(so);
+ CORBA_free(sr);
+ return -1;
+}
+
+static int string2_test(IC_Env *env)
+{
+ char* sa[3] = {"hello", "foo", "bar"};
+ m_sseq ssi = {3, 3, sa};
+ m_sseq *sso, *ssr;
+
+ fprintf(stdout, "\n======== m_i_string2 test ======\n\n");
+ ssr = m_i_string2_test(NULL, &ssi, &sso, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_sseq(&ssi, sso) && cmp_sseq(&ssi, sso));
+ if (!cmp_sseq(&ssi, sso)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_sseq(&ssi);
+ fprintf(stdout, "got:\n");
+ print_sseq(sso);
+ }
+ if (!cmp_sseq(&ssi, ssr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_sseq(&ssi);
+ fprintf(stdout, "got:\n");
+ print_sseq(ssr);
+ }
+ CORBA_free(sso);
+ CORBA_free(ssr);
+ return -1;
+}
+
+static int string3_test(IC_Env *env)
+{
+ char* si = longtext;
+ char* so;
+ char* sr;
+
+ fprintf(stdout, "\n======== m_i_string3 test ======\n\n");
+ sr = m_i_string3_test(NULL, si, &so, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_str(si, so) && cmp_str(si, so));
+ if (!cmp_str(si, so))
+ fprintf(stdout, " out parameter error, sent: %s, got: %s\n", si, so);
+ if (!cmp_str(si, sr))
+ fprintf(stdout, " result error, sent: %s, got: %s\n", si, sr);
+ CORBA_free(so);
+ CORBA_free(sr);
+ return -1;
+}
+
+static int string4_test(IC_Env *env)
+{
+ char as1[100] = "a string", as2[200] = "help", as3[200] = "hello there";
+ m_strRec stri = { 1, /* dd */
+ as1, /* str4 */
+ {{'a', 'k'}, {'z', 'g'}, {'n', 'q'}}, /* str7 */
+ {3, 3, "buf"}, /* str5 */
+ as2, /* str6 */
+ {'m', 'f', 'o'}, /* str8 */
+ as3, /* str9 */
+ {3, 3, "stu"} /* str10 */
+ };
+ m_strRec *stro, *strr;
+
+ fprintf(stdout, "\n======== m_i_string4 test ======\n\n");
+ strr = m_i_string4_test(NULL, &stri, &stro, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_strRec(&stri,stro) && cmp_strRec(&stri,strr));
+ if (!cmp_strRec(&stri,stro)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_strRec(&stri);
+ fprintf(stdout, " got:\n");
+ print_strRec(stro);
+ fprintf(stdout, "\n");
+ }
+ if (!cmp_strRec(&stri,strr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_strRec(&stri);
+ fprintf(stdout, " got:\n");
+ print_strRec(strr);
+ fprintf(stdout, "\n");
+ }
+ CORBA_free(stro);
+ CORBA_free(strr);
+ return -1;
+}
+
+
+static int pid_test(IC_Env *env)
+{
+ erlang_pid pid = {"", 7, 0, 0}, pido, pidr;
+
+ strcpy(pid.node, this_node), /* this currently running node */
+ fprintf(stdout, "\n======== m_i_pid test ======\n\n");
+ pidr = m_i_pid_test(NULL, &pid, &pido, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_pid(&pid, &pido) && cmp_pid(&pid, &pidr));
+ if (!cmp_pid(&pid, &pido)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_pid(&pid);
+ fprintf(stdout, "got:\n");
+ print_pid(&pido);
+ }
+ if (!cmp_pid(&pid, &pidr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_pid(&pid);
+ fprintf(stdout, "got:\n");
+ print_pid(&pidr);
+ }
+ return -1;
+}
+
+static int port_test(IC_Env *env)
+{
+ erlang_port porti = {"node", 5, 1}, porto, portr;
+
+ fprintf(stdout, "\n======== m_i_port test ======\n\n");
+ portr = m_i_port_test(NULL, &porti, &porto, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_port(&porti, &porto) && cmp_port(&porti, &portr));
+ if (!cmp_port(&porti, &porto)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_port(&porti);
+ fprintf(stdout, "got:\n");
+ print_port(&porto);
+ }
+ if (!cmp_port(&porti, &portr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_port(&porti);
+ fprintf(stdout, "got:\n");
+ print_port(&portr);
+ }
+ return -1;
+}
+
+static int ref_test(IC_Env *env)
+{
+ erlang_ref refi = { "node1", 3, {1, 2, 3}, 1},
+ refo, refr;
+
+ fprintf(stdout, "\n======== m_i_ref test ======\n\n");
+ refr = m_i_ref_test(NULL, &refi, &refo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_ref(&refi, &refo) && cmp_ref(&refi, &refr));
+ if (!cmp_ref(&refi, &refo)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_ref(&refi);
+ fprintf(stdout, "got:\n");
+ print_ref(&refo);
+ }
+ if (!cmp_ref(&refi, &refr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_ref(&refi);
+ fprintf(stdout, "got:\n");
+ print_ref(&refr);
+ }
+ return -1;
+}
+
+static int term_test(IC_Env *env)
+{
+ ETERM *ti, *to, *tr;
+
+ ti = erl_format("[{hej, 1, 23}, \"string\", {1.23, 45}]");
+
+ fprintf(stdout, "\n======== m_i_term test ======\n\n");
+ tr = m_i_term_test(NULL, ti, &to, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(erl_match(ti, to) && erl_match(ti, tr));
+ if (!erl_match(ti, to)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_term(ti);
+ fprintf(stdout, "got:\n");
+ print_term(to);
+ }
+ if (!erl_match(ti, tr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_term(ti);
+ fprintf(stdout, "got:\n");
+ print_term(tr);
+ }
+ erl_free_term(ti);
+ erl_free_term(to);
+ erl_free_term(tr);
+ return -1;
+}
+
+static int typedef_test(IC_Env *env)
+{
+ m_banan mbi, mbo; /* erlang_port */
+ m_apa mai; /* ETERM* */
+ m_apa mao = NULL;
+ long tl;
+
+ strcpy(mbi.node,"node");
+ mbi.id = 15;
+ mbi.creation = 1;
+
+ fprintf(stdout, "\n======== m_i_typedef test ======\n\n");
+ mai = erl_format("[{hej, 1, 23}, \"string\", {1.23, 45}]");
+ tl = m_i_typedef_test(NULL, mai, &mbi, &mao, &mbo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(erl_match(mai, mao) && cmp_port(&mbi, &mbo) && tl == 4711);
+ if (!erl_match(mai, mao)) {
+ fprintf(stdout, " out parameter error (term), sent:\n");
+ print_term(mai);
+ fprintf(stdout, "got:\n");
+ print_term(mao);
+ }
+ if (!cmp_port(&mbi, &mbo)) {
+ fprintf(stdout, " out parameter error (port), sent:\n");
+ print_port(&mbi);
+ fprintf(stdout, "got:\n");
+ print_port(&mbo);
+ }
+ if (tl != 4711) {
+ fprintf(stdout, " result error, sent: 4711, got %ld\n", tl);
+ }
+ erl_free_term(mai);
+ erl_free_term(mao);
+ return -1;
+}
+
+static int inline_sequence_test(IC_Env *env)
+{
+ int i;
+ long al[500];
+ m_s isi = {4711, {500, 10, al}},
+ *iso, *isr;
+
+ for (i = 0; i < 500; i++)
+ al[i]=i;
+ fprintf(stdout, "\n======== m_i_inline_sequence test ======\n\n");
+ isr = m_i_inline_sequence_test(NULL, &isi, &iso, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_s(&isi, iso) && cmp_s(&isi, isr));
+ if (!cmp_s(&isi, iso)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_s(&isi);
+ fprintf(stdout, "got:\n");
+ print_s(iso);
+ }
+ if (!cmp_s(&isi, isr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_s(&isi);
+ fprintf(stdout, "got:\n");
+ print_s(isr);
+ }
+ CORBA_free(iso);
+ CORBA_free(isr);
+ return -1;
+}
+
+static int term_sequence_test(IC_Env *env)
+{
+ ETERM* et_array[4] = {
+ erl_format("[{apa, 1, 23}, \"string\", {1.23, 45}]"),
+ erl_format("[{banan, 1, 23}, \"string\", {1.23, 45}]"),
+ erl_format("[{apelsin, 1, 23}, \"string\", {1.23, 45}]"),
+ erl_format("[{mango, 1, 23}, \"string\", {1.23, 45}]")};
+ m_etseq etsi = {4, 4, et_array}, *etso, *etsr;
+
+ fprintf(stdout, "\n======== m_i_term_sequence test ======\n\n");
+ etsr = m_i_term_sequence_test(NULL, &etsi, &etso, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_etseq(&etsi, etso) && cmp_etseq(&etsi, etsr));
+ if (!cmp_etseq(&etsi, etso)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_etseq(&etsi);
+ fprintf(stdout, "got:\n");
+ print_etseq(etso);
+ }
+ if (!cmp_etseq(&etsi, etsr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_etseq(&etsi);
+ fprintf(stdout, "got:\n");
+ print_etseq(etsr);
+ }
+ free_etseq_buf(&etsi);
+ free_etseq_buf(etso);
+ free_etseq_buf(etsr);
+ CORBA_free(etso);
+ CORBA_free(etsr);
+ return -1;
+}
+
+static int term_struct_test(IC_Env *env)
+{
+ m_et eti = { erl_format("[{hej, 1, 23}, \"string\", {1.23, 45}]"),
+ 121212 };
+ m_et eto, etr;
+
+ fprintf(stdout, "\n======== m_i_term_struct test ======\n\n");
+ etr = m_i_term_struct_test(NULL, &eti, &eto, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_et(&eti, &eto) && cmp_et(&eti, &etr));
+ if (!cmp_et(&eti, &eto)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_et(&eti);
+ fprintf(stdout, "got:\n");
+ print_et(&eto);
+ }
+ if (!cmp_et(&eti, &etr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_et(&eti);
+ fprintf(stdout, "got:\n");
+ print_et(&etr);
+ }
+ free_et(&eti);
+ free_et(&eto);
+ free_et(&etr);
+ return -1;
+}
+
+static int wstring1_test(IC_Env *env)
+{
+ CORBA_wchar wsi[] = {100, 101, 102, 103, 104, 0}, *wso, *wsr;
+
+ fprintf(stdout, "\n======== m_i_wstring1 test ======\n\n");
+ wsr = m_i_wstring1_test(NULL, wsi, &wso, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_wstr(wsi, wso) && cmp_wstr(wsi, wsr));
+ if (!cmp_wstr(wsi, wso)) {
+ fprintf(stdout, " out parameter error, sent: \n");
+ print_wstr(wsi);
+ fprintf(stdout, "got:\n");
+ print_wstr(wso);
+ }
+ if (!cmp_wstr(wsi, wsr)) {
+ fprintf(stdout, " result error, sent: \n");
+ print_wstr(wsi);
+ fprintf(stdout, "got:\n");
+ print_wstr(wsr);
+ }
+ CORBA_free(wso);
+ CORBA_free(wsr);
+ return -1;
+}
+
+/* Compare functions */
+static int cmp_aseq(m_aseq *a1, m_aseq *a2)
+{
+ int i;
+
+ if (a1->_length != a2->_length)
+ return 0;
+ for (i = 0; i < a1->_length; i++)
+ if (cmp_a(&(a1->_buffer[i]), &(a2->_buffer[i])) == 0)
+ return 0;
+ return 1;
+}
+
+static int cmp_a(m_a *a1, m_a *a2)
+{
+ return a1->l == a2->l &&
+ a1->d == a2->d &&
+ cmp_bseq(&a1->y, &a2->y);
+}
+
+static int cmp_bseq(m_bseq *b1, m_bseq *b2)
+{
+ int i;
+
+ if (b1->_length != b2->_length)
+ return 0;
+ for (i = 0; i < b1->_length; i++)
+ if (cmp_b(&(b1->_buffer[i]), &(b2->_buffer[i])) == 0)
+ return 0;
+ return 1;
+}
+
+static int cmp_b(m_b *b1, m_b *b2)
+{
+ return b1->l == b2->l && b1->c == b2->c;
+}
+
+static int cmp_lseq(m_lseq *b1, m_lseq *b2)
+{
+ int i;
+
+ if (b1->_length != b2->_length)
+ return 0;
+ for (i = 0; i < b1->_length; i++)
+ if (b1->_buffer[i] != b2->_buffer[i])
+ return 0;
+ return 1;
+}
+
+static int cmp_etseq(m_etseq *b1, m_etseq *b2)
+{
+ int i;
+
+ if (b1->_length != b2->_length)
+ return 0;
+ for (i = 0; i < b1->_length; i++)
+ if (!erl_match(b1->_buffer[i], b2->_buffer[i]))
+ return 0;
+ return 1;
+}
+
+static int cmp_et(m_et* b1, m_et *b2)
+{
+ return erl_match(b1->e, b2->e) && b1->l == b2->l;
+}
+
+static int cmp_es(m_es *b1, m_es *b2)
+{
+ return b1->f == b2->f && b1->l == b2->l;
+}
+
+static int cmp_arr1(m_arr1 b1, m_arr1 b2)
+{
+ int i;
+
+ for (i = 0; i < 500; i++)
+ if (b1[i] != b2[i])
+ return 0;
+ return 1;
+}
+
+static int cmp_dd(m_dd b1, m_dd b2)
+{
+
+ int i, j;
+
+ for (i = 0; i < 2; i++)
+ for (j = 0; j < 3; j++)
+ if (b1[i][j] != b2[i][j])
+ return 0;
+ return 1;
+}
+
+
+
+static int cmp_strRec(m_strRec *b1, m_strRec *b2)
+{
+ int i, j;
+
+ if (b1->bb != b2->bb)
+ return 0;
+ if (!cmp_str(b1->str4,b2->str4))
+ return 0;
+ if (b1->str5._length != b2->str5._length)
+ return 0;
+ for (j = 0; j < b1->str5._length; j++)
+ if (b1->str5._buffer[j] != b2->str5._buffer[j])
+ return 0;
+ if (!cmp_str(b1->str6,b2->str6))
+ return 0;
+ for (i = 0; i < 2; i++)
+ for (j = 0; j < 3; j++)
+ if (b1->str7[i][j] != b2->str7[i][j])
+ return 0;
+ for (j = 0; j < 3; j++)
+ if (b1->str8[j] != b2->str8[j])
+ return 0;
+ if (!cmp_str(b1->str9,b2->str9))
+ return 0;
+ if (b1->str10._length != b2->str10._length)
+ return 0;
+ for (j = 0; j < b1->str10._length; j++)
+ if (b1->str10._buffer[j] != b2->str10._buffer[j])
+ return 0;
+ return 1;
+}
+
+
+static int cmp_sseq(m_sseq *b1, m_sseq *b2)
+{
+ int i;
+
+ if (b1->_length != b2->_length)
+ return 0;
+ for (i = 0; i < b1->_length; i++)
+ if (!cmp_str(b1->_buffer[i], b2->_buffer[i]))
+ return 0;
+ return 1;
+}
+
+
+static int cmp_pid(erlang_pid *p1, erlang_pid *p2)
+{
+ return cmp_str(p1->node,p2-> node) &&
+ p1->num == p2->num &&
+ p1->serial == p2->serial &&
+ p1->creation == p2->creation;
+}
+
+static int cmp_port(erlang_port *p1, erlang_port *p2)
+{
+ return cmp_str(p1->node,p2-> node) && p1->id == p2->id;
+}
+
+static int cmp_ref(erlang_ref *p1, erlang_ref *p2)
+{
+ return cmp_str(p1->node, p2->node) &&
+ p1->len == p2->len &&
+ (p1->len < 1 || p1->n[0] == p2->n[0]) &&
+ (p1->len < 2 || p1->n[1] == p2->n[1]) &&
+ (p1->len < 3 || p1->n[2] == p2->n[2]);
+}
+
+static int cmp_s(m_s *b1, m_s *b2)
+{
+ int i;
+
+ if (b1->l != b2->l)
+ return 0;
+ if (b1->sl._length != b2->sl._length)
+ return 0;
+ for (i = 0; i < b1->sl._length; i++)
+ if (b1->sl._buffer[i] != b2->sl._buffer[i])
+ return 0;
+ return 1;
+}
+
+
+static int cmp_ssstr3(m_ssstr3 *b1, m_ssstr3 *b2)
+{
+ int i,j;
+
+ if (b1->_length != b2->_length)
+ return 0;
+ for (i = 0; i < b1->_length; i++) {
+ if (b1->_buffer[i]._length != b2->_buffer[i]._length)
+ return 0;
+ for (j = 0; j < b1->_buffer[i]._length; j++)
+ if (!cmp_str(b1->_buffer[i]._buffer[j],
+ b2->_buffer[i]._buffer[j]))
+ return 0;
+ }
+ return 1;
+}
+
+
+
+static int cmp_ssarr3(m_ssarr3 *b1, m_ssarr3 *b2)
+{
+ int i;
+
+ if (b1->_length != b2->_length)
+ return 0;
+ for (i = 0; i < b1->_length; i++) {
+ if (!cmp_sarr3(&b1->_buffer[i], &b2->_buffer[i]))
+ return 0;
+ }
+ return 1;
+}
+
+static int cmp_sarr3(m_sarr3 *b1, m_sarr3 *b2)
+{
+ int i;
+
+ if (b1->_length != b2->_length)
+ return 0;
+ for (i = 0; i < b1->_length; i++) {
+ if (!cmp_arr3(b1->_buffer[i], b2->_buffer[i]))
+ return 0;
+ }
+ return 1;
+}
+
+static int cmp_arr3(m_arr3 b1, m_arr3 b2)
+{
+ int i;
+
+ for (i = 0; i < sizeof(m_arr3)/sizeof(CORBA_long); i++) {
+ if (b1[i] != b2[i])
+ return 0;
+ }
+ return 1;
+}
+
+/* Print functions */
+static void print_aseq(m_aseq *a)
+{
+ int i;
+ fprintf(stdout, "\nm_aseq size: %ld --------\n", a->_length);
+ for (i = 0; i < a->_length; i++)
+ print_a(&(a->_buffer[i]));
+}
+
+static void print_a(m_a *a)
+{
+ fprintf(stdout, "\nm_a --------\n l: %ld\n d:%f\n", a->l, a->d);
+ print_bseq(&a->y);
+}
+
+static void print_bseq(m_bseq *b)
+{
+ int i;
+
+ fprintf(stdout, "\nm_bseq size: %ld --------\n",b->_length);
+ for (i = 0; i < b->_length; i++)
+ print_b(&(b->_buffer[i]));
+}
+
+static void print_lseq(m_lseq *b)
+{
+ int i;
+
+ fprintf(stdout, "\nm_lseq size: %ld --------\n",b->_length);
+ for (i = 0; i < b->_length; i++)
+ fprintf(stdout, "[%d]: %ld\n", i, b->_buffer[i]);
+}
+
+static void print_b(m_b *b)
+{
+ fprintf(stdout, "\nm_b --------\n l: %ld\n c: %c\n", b->l, b->c);
+}
+
+
+static void print_etseq(m_etseq *b)
+{
+ int i;
+
+ for (i = 0; i < b->_length; i++) {
+ fprintf(stdout, "[%d]:\n", i);
+ erl_print_term(stdout, b->_buffer[i]);
+ }
+}
+
+
+static void print_et(m_et* b)
+{
+ fprintf(stdout, "\net struct --------\n");
+ erl_print_term(stdout, b->e);
+ fprintf(stdout, "long: %ld\n", b->l);
+ fprintf(stdout, "\n--------\n");
+}
+
+static void print_es(m_es *b)
+{
+ fprintf(stdout, "\nm_es --------\n f: %d\n l: %ld\n", b->f, b->l);
+}
+
+
+static void print_arr1(long a[10])
+{
+ int i;
+
+ for (i = 0; i < 10; i++)
+ fprintf(stdout, "\n[%d]: %ld\n", i, a[i]);
+}
+
+static void print_dd(long a[2][3])
+{
+ int i, j;
+
+ fprintf(stdout, "\nlong dd[2][3] --------\n");
+ for (i = 0; i < 2; i++)
+ for (j = 0; j < 3; j++)
+ fprintf(stdout, "\n[%d][%d]: %ld\n", i, j, a[i][j]);
+}
+
+
+static void print_strRec(m_strRec* sr)
+{
+ int i, j;
+
+ fprintf(stdout, "\nboolean bb : %d\n",sr->bb);
+ fprintf(stdout, "string str4 : %s\n",sr->str4);
+ fprintf(stdout, "str7[2][3] :\n");
+ for (i = 0; i < 2; i++)
+ for (j = 0; j < 3; j++)
+ fprintf(stdout, "str7[%d][%d]: %ld\n", i, j, sr->str7[i][j]);
+ fprintf(stdout, "str5._length : %ld\n",sr->str5._length);
+ for (j = 0; j < sr->str5._length; j++)
+ fprintf(stdout, "str5._buffer[%d]: %c\n", j, sr->str5._buffer[j]);
+ fprintf(stdout, "string str6 : %s\n",sr->str6);
+ fprintf(stdout, "str8 :\n");
+ for (j = 0; j < 3; j++)
+ fprintf(stdout, "str8[%d]: %c\n", j, sr->str8[j]);
+ fprintf(stdout, "string str9 : %s\n",sr->str9);
+ fprintf(stdout, "str10._length : %ld\n",sr->str10._length);
+ for (j = 0; j < sr->str10._length; j++)
+ fprintf(stdout, "str10._buffer[%d]: %c\n", j, sr->str10._buffer[j]);
+}
+
+static void print_sseq(m_sseq *b)
+{
+ int i;
+
+ fprintf(stdout, "\nm_sseq size: %ld --------\n",b->_length);
+ for (i = 0; i < b->_length; i++)
+ fprintf(stdout, "%s\n", b->_buffer[i]);
+
+}
+
+
+static void print_pid(erlang_pid *p)
+{
+ fprintf(stdout, "\nerlang_pid --------\n node: %s\n num: %d\n "
+ "serial: %d\n creation: %d\n",
+ p->node, p->num, p->serial, p->creation);
+}
+
+static void print_port(erlang_port *p)
+{
+ fprintf(stdout, "\nerlang_port --------\n node: %s\n id: %d\n "
+ "creation: %d\n", p->node, p->id, p->creation);
+}
+
+static void print_ref(erlang_ref *p)
+{
+ fprintf(stdout, "\nerlang_ref --------\n node: %s\n len: %d\n "
+ "n[0]: %d\n n[1]: %d\n n[2]: %d\n creation: %d\n",
+ p->node, p->len, p->n[0], p->n[1], p->n[2], p->creation);
+}
+
+static void print_term(ETERM *t)
+{
+ fprintf(stdout, "\nETERM --------\n");
+ erl_print_term(stdout, t);
+ fprintf(stdout, "\n--------\n");
+}
+
+static void print_s(m_s *p)
+{
+ int i;
+
+ fprintf(stdout, "\n%ld\n", p->l);
+ for (i = 0; i < p->sl._length; i++)
+ fprintf(stdout, "\n[%d]: %ld\n", i, p->sl._buffer[i]);
+}
+
+
+static void print_ssstr3(m_ssstr3 *b1)
+{
+ int i,j;
+
+ fprintf(stdout, "\nSSSTR3 --------\n");
+ fprintf(stdout,"b1->_length = %ld\n",b1->_length);
+ for (i = 0; i < b1->_length; i++) {
+ fprintf(stdout,"\nb1->_buffer[%d]._length %ld\n",
+ i, b1->_buffer[i]._length);
+ for (j = 0; j < b1->_buffer[i]._length; j++)
+ fprintf(stdout,"b1->_buffer[%d]._buffer[%d] = %s\n",
+ i, j, b1->_buffer[i]._buffer[j]);
+ }
+ fprintf(stdout, "\n--------\n");
+}
+
+static void print_wstr(CORBA_wchar *ws)
+{
+ int i = 0;
+
+ fprintf(stdout, "\nwstr --------\n");
+ while (ws[i]) {
+ fprintf(stdout, "[%d]: %ld\n", i, ws[i]);
+ i++;
+ }
+ fprintf(stdout, "\n--------\n");
+}
+
+
+static void print_ssarr3(m_ssarr3 *b1)
+{
+ int i;
+
+ fprintf(stdout, "\nssarr3 --------\n");
+ fprintf(stdout,"length: %ld\n",b1->_length);
+ fprintf(stdout, "buffer:\n");
+ for (i = 0; i < b1->_length; i++)
+ print_sarr3(&b1->_buffer[i]);
+ fprintf(stdout, "\n--------\n");
+}
+
+static void print_sarr3(m_sarr3 *b1)
+{
+ int i;
+
+ fprintf(stdout, "\nsarr3 --------\n");
+ fprintf(stdout,"length: %ld\n",b1->_length);
+ fprintf(stdout, "buffer:\n");
+ for (i = 0; i < b1->_length; i++)
+ print_arr3(b1->_buffer[i]);
+ fprintf(stdout, "\n--------\n");
+}
+
+static void print_arr3(m_arr3 b1)
+{
+ int i;
+
+ fprintf(stdout, "\narr3 --------\n");
+ for (i = 0; i < sizeof(m_arr3)/sizeof(CORBA_long); i++)
+ fprintf(stdout, "%ld ", b1[i]);
+ fprintf(stdout, "\n--------\n");
+}
+
+static void free_etseq_buf(m_etseq *b)
+{
+ int i;
+
+ for (i = 0; i < b->_length; i++)
+ erl_free_term(b->_buffer[i]);
+}
+
+static void free_et(m_et* b)
+{
+ erl_free_term(b->e);
+}
+
+static void showtime(MyTimeval *start, MyTimeval *stop)
+{
+ MyTimeval elapsed;
+
+ elapsed.tv_sec = stop->tv_sec - start->tv_sec;
+ elapsed.tv_usec = stop->tv_usec - start->tv_usec;
+ while (elapsed.tv_usec < 0) {
+ elapsed.tv_sec -= 1;
+ elapsed.tv_usec += 1000000;
+ }
+ fprintf(stderr,"%ld.%06ld seconds\n",elapsed.tv_sec, elapsed.tv_usec);
+}
+
+static void my_gettimeofday(MyTimeval *tv)
+#ifdef __WIN32__
+#define EPOCH_JULIAN_DIFF 11644473600i64
+{
+ SYSTEMTIME t;
+ FILETIME ft;
+ LONGLONG lft;
+
+ GetSystemTime(&t);
+ SystemTimeToFileTime(&t, &ft);
+ memcpy(&lft, &ft, sizeof(lft));
+ tv->tv_usec = (long) ((lft / 10i64) % 1000000i64);
+ tv->tv_sec = (long) ((lft / 10000000i64) - EPOCH_JULIAN_DIFF);
+}
+#elif defined VXWORKS
+{
+ int rate = sysClkRateGet(); /* Ticks per second */
+ unsigned long ctick = tickGet();
+ tv->tv_sec = ctick / rate; /* secs since reboot */
+ tv->tv_usec = ((ctick - (tv->tv_sec * rate))*1000000)/rate;
+}
+#else
+{
+ gettimeofday(tv, NULL);
+}
+#endif
diff --git a/lib/ic/test/c_client_erl_server_SUITE_data/c_erl_test.idl b/lib/ic/test/c_client_erl_server_SUITE_data/c_erl_test.idl
new file mode 100644
index 0000000000..ccb8f54508
--- /dev/null
+++ b/lib/ic/test/c_client_erl_server_SUITE_data/c_erl_test.idl
@@ -0,0 +1,174 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 2001-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+#include "erlang.idl"
+
+
+const short TestConst = 1;
+
+module m {
+
+ const short TestConst = 2;
+
+ struct b {
+ long l;
+ char c;
+ };
+
+ struct simple {
+ long l;
+ b b_t;
+ };
+
+ enum fruit {orange, banana, apple, peach, pear};
+
+ typedef sequence<long> lseq;
+
+ typedef sequence<b> bseq;
+
+ struct a {
+ long l;
+ bseq y;
+ double d;
+ };
+
+ typedef sequence<a> aseq;
+
+ typedef sequence<string> sseq;
+ typedef string str;
+ typedef long myLong;
+
+ typedef long arr1[500], dd[2][3];
+
+ typedef erlang::term apa;
+ typedef erlang::port banan;
+
+ typedef sequence<erlang::term> etseq;
+
+ struct s {
+ long l;
+ sequence<long> sl;
+ };
+
+ struct es {
+ fruit f;
+ myLong l;
+ };
+
+ struct et {
+ erlang::term e;
+ long l;
+ };
+
+
+ typedef sequence<char> str1;
+ typedef string<12> str2;
+ typedef char str3[3];
+
+ typedef sequence<string> sstr3; // sequence of string
+ typedef sequence<sstr3> ssstr3; // sequence of sequences of strings
+
+ typedef long arr3[3]; // array of long
+ typedef sequence<arr3> sarr3; // sequence of array
+ typedef sequence<sarr3> ssarr3; // sequence of sequnces of arrays of strings
+
+ struct strRec{
+ boolean bb;
+ string str4;
+ long str7[3][2];
+ sequence<char> str5;
+ string<12> str6;
+ str3 str8;
+ str2 str9;
+ str1 str10;
+ };
+
+
+ struct dyn {
+ long l;
+ sequence<long> sl;
+ };
+ typedef dyn arr2[1][2];
+
+
+ interface i {
+
+ const short TestConst = 3;
+
+ //arr2 suck(in arr2 x, out arr2 y );
+
+ ///////////////////////////////// attribute long l;
+
+ // simple types
+ void void_test();
+ long long_test(in long a, out long a1);
+ long long longlong_test(in long long a, out long long a1);
+ unsigned short ushort_test(in unsigned short a, out unsigned short a1);
+ unsigned long ulong_test(in unsigned long a, out unsigned long a1);
+ unsigned long long ulonglong_test(in unsigned long long a, out unsigned long long a1);
+ double double_test(in double a, out double a1);
+ char char_test(in char a, out char a1);
+ wchar wchar_test(in wchar a, out wchar a1);
+ octet octet_test(in octet a, out octet a1);
+ boolean bool_test(in boolean a, out boolean a1);
+
+ // Seq. and struct tests
+ b struct_test(in b a, out b a1);
+ es struct2_test(in es a, out es a1);
+ //simple struct3_test(in simple x, out simple y);
+ bseq seq1_test(in bseq a, out bseq a1);
+ aseq seq2_test(in aseq a, out aseq a1);
+ lseq seq3_test(in lseq a, out lseq a1);
+ ssstr3 seq4_test(in ssstr3 a, out ssstr3 a1);
+ ssarr3 seq5_test(in ssarr3 a, out ssarr3 a1);
+
+ // Array tests
+ arr1 array1_test(in arr1 a, out arr1 a1);
+ dd array2_test(in dd a, out dd a1);
+
+ // enum test
+ fruit enum_test(in fruit a, out fruit a1);
+
+ // string tests
+ string string1_test(in string a, out string a1);
+ wstring wstring1_test(in wstring a, out wstring a1);
+ sseq string2_test(in sseq a, out sseq a1);
+ str string3_test(in str a, out str a1);
+ strRec string4_test(in strRec a, out strRec a1);
+
+ // Special erlang types
+ erlang::pid pid_test(in erlang::pid a, out erlang::pid a1);
+ erlang::port port_test(in erlang::port a, out erlang::port a1);
+ erlang::ref ref_test(in erlang::ref a, out erlang::ref a1);
+ erlang::term term_test(in erlang::term a, out erlang::term a1);
+
+ // typedef test
+ long typedef_test(in apa a, in banan b, out apa a1, out banan b1);
+
+ // inlined seq. test
+ s inline_sequence_test(in s a, out s a1);
+
+ // term seq. test
+ etseq term_sequence_test(in etseq a, out etseq a1);
+ // term struct test
+ et term_struct_test(in et a, out et a1);
+
+ };
+
+};
diff --git a/lib/ic/test/c_client_erl_server_SUITE_data/erl_server.erl b/lib/ic/test/c_client_erl_server_SUITE_data/erl_server.erl
new file mode 100644
index 0000000000..dffbbb059c
--- /dev/null
+++ b/lib/ic/test/c_client_erl_server_SUITE_data/erl_server.erl
@@ -0,0 +1,28 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+-module(erl_server).
+
+-export([run/0, stop/0]).
+
+run() ->
+ m_i:oe_create().
+
+stop() ->
+ gen_server:cast(cidl_test, stop).
diff --git a/lib/ic/test/c_client_erl_server_SUITE_data/m_i_impl.erl b/lib/ic/test/c_client_erl_server_SUITE_data/m_i_impl.erl
new file mode 100644
index 0000000000..cfcaa793a5
--- /dev/null
+++ b/lib/ic/test/c_client_erl_server_SUITE_data/m_i_impl.erl
@@ -0,0 +1,161 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+-module(m_i_impl).
+-include("m.hrl").
+
+-export([init/1, terminate/2, void_test/1, long_test/2, ushort_test/2,
+ longlong_test/2, ulong_test/2, ulonglong_test/2,
+ double_test/2, char_test/2, wchar_test/2, octet_test/2,
+ bool_test/2, struct_test/2, struct2_test/2, seq1_test/2,
+ seq2_test/2, seq3_test/2, seq4_test/2, seq5_test/2,
+ array1_test/2, array2_test/2, enum_test/2, string1_test/2,
+ string2_test/2, string3_test/2, string4_test/2, pid_test/2,
+ port_test/2, ref_test/2, term_test/2, typedef_test/3,
+ inline_sequence_test/2, '_set_l'/2, '_get_l'/1,
+ term_struct_test/2, term_sequence_test/2, wstring1_test/2]).
+
+-define(PRINTDEBUG(Case),
+ io:format("erl_server: case: ~p~n"
+ "erl_server: location: ~p~n", [Case, [?FILE, ?LINE]])).
+-define(PRINTDEBUG2(Case, Msg),
+ io:format("erl_server: case: ~p~n"
+ "erl_server: Msg: ~p~n"
+ "erl_server: location: ~p~n", [Case, Msg, [?FILE, ?LINE]])).
+
+init(Env) ->
+ {ok, []}.
+
+terminate(F, R) ->
+ ok.
+
+'_get_l'(State) ->
+ ?PRINTDEBUG("_get_l"),
+ {reply, State, State}.
+void_test(State) ->
+ ?PRINTDEBUG("void_test"),
+ {reply, ok, State}.
+
+'_set_l'(State, V) ->
+ ?PRINTDEBUG2("_set_l", V),
+ {reply, ok, V}.
+ushort_test(State, V) ->
+ ?PRINTDEBUG2("ushort_test", V),
+ {reply, {V, V}, State}.
+long_test(State, V) ->
+ ?PRINTDEBUG2("long_test", V),
+ {reply, {V, V}, State}.
+longlong_test(State, V) ->
+ ?PRINTDEBUG2("longlong_test", V),
+ {reply, {V, V}, State}.
+ulong_test(State, V) ->
+ ?PRINTDEBUG2("ulong_test", V),
+ {reply, {V, V}, State}.
+ulonglong_test(State, V) ->
+ ?PRINTDEBUG2("ulonglong_test", V),
+ {reply, {V, V}, State}.
+double_test(State, V) ->
+ ?PRINTDEBUG2("double_test", V),
+ {reply, {V, V}, State}.
+char_test(State, V) ->
+ ?PRINTDEBUG2("char_test", V),
+ {reply, {V, V}, State}.
+wchar_test(State, V) ->
+ ?PRINTDEBUG2("wchar_test", V),
+ {reply, {V, V}, State}.
+octet_test(State, V) ->
+ ?PRINTDEBUG2("octet_test", V),
+ {reply, {V, V}, State}.
+bool_test(State, V) ->
+ ?PRINTDEBUG2("bool_test", V),
+ {reply, {V, V}, State}.
+
+struct_test(State, V) ->
+ ?PRINTDEBUG2("struct_test", V),
+ {reply, {V, V}, State}.
+struct2_test(State, V) ->
+ ?PRINTDEBUG2("struct2_test", V),
+ {reply, {V, V}, State}.
+seq1_test(State, V) ->
+ ?PRINTDEBUG2("seq1_test", V),
+ {reply, {V, V}, State}.
+seq2_test(State, V) ->
+ ?PRINTDEBUG2("seq2_test", V),
+ {reply, {V, V}, State}.
+seq3_test(State, V) ->
+ ?PRINTDEBUG2("seq3_test", V),
+ {reply, {V, V}, State}.
+seq4_test(State, V) ->
+ ?PRINTDEBUG2("seq4_test", V),
+ {reply, {V, V}, State}.
+seq5_test(State, V) ->
+ ?PRINTDEBUG2("seq5_test", V),
+ {reply, {V, V}, State}.
+array1_test(State, V) ->
+ ?PRINTDEBUG2("array1_test", V),
+ {reply, {V, V}, State}.
+array2_test(State, V) ->
+ ?PRINTDEBUG2("array2_test", V),
+ {reply, {V, V}, State}.
+enum_test(State, V) ->
+ ?PRINTDEBUG2("enum_test", V),
+ {reply, {V, V}, State}.
+string1_test(State, V) ->
+ ?PRINTDEBUG2("string1_test", V),
+ {reply, {V, V}, State}.
+string2_test(State, V) ->
+ ?PRINTDEBUG2("string2_test", V),
+ {reply, {V, V}, State}.
+string3_test(State, V) ->
+ ?PRINTDEBUG2("string3_test", V),
+ {reply, {V, V}, State}.
+string4_test(State, V) ->
+ ?PRINTDEBUG2("string4_test", V),
+ {reply, {V, V}, State}.
+pid_test(State, V) ->
+ ?PRINTDEBUG2("pid_test", V),
+ {reply, {V, V}, State}.
+port_test(State, V) ->
+ ?PRINTDEBUG2("port_test", binary_to_list(term_to_binary(V))),
+ {reply, {V, V}, State}.
+ref_test(State, V) ->
+ ?PRINTDEBUG2("ref_test", binary_to_list(term_to_binary(V))),
+ {reply, {V, V}, State}.
+term_test(State, V) ->
+ ?PRINTDEBUG2("term_test", V),
+ {reply, {V, V}, State}.
+typedef_test(State, A, B) ->
+ ?PRINTDEBUG2("typedef_test", [A,B]),
+ {reply, {4711, A, B}, State}.
+inline_sequence_test(State, V) ->
+ ?PRINTDEBUG2("inline_sequence_test", V),
+ {reply, {V, V}, State}.
+term_sequence_test(State, V) ->
+ ?PRINTDEBUG2("term_sequence_test", V),
+ {reply, {V, V}, State}.
+term_struct_test(State, V) ->
+ ?PRINTDEBUG2("term_struct_test", V),
+ {reply, {V, V}, State}.
+wstring1_test(State, V) ->
+ ?PRINTDEBUG2("wstring1_test", V),
+ {reply, {V, V}, State}.
+
+
+
+
diff --git a/lib/ic/test/c_client_erl_server_proto_SUITE.erl b/lib/ic/test/c_client_erl_server_proto_SUITE.erl
new file mode 100644
index 0000000000..58309a2221
--- /dev/null
+++ b/lib/ic/test/c_client_erl_server_proto_SUITE.erl
@@ -0,0 +1,315 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+
+%%----------------------------------------------------------------------
+%% Purpose : Test suite for c-client/erl-server
+%%----------------------------------------------------------------------
+
+-module(c_client_erl_server_proto_SUITE).
+-include("test_server.hrl").
+
+-export([init_per_testcase/2, fin_per_testcase/2,
+ all/1, void_test/1, long_test/1, long_long_test/1,
+ unsigned_short_test/1, unsigned_long_test/1,
+ unsigned_long_long_test/1, double_test/1, char_test/1,
+ wchar_test/1, octet_test/1, bool_test/1, struct_test/1,
+ struct2_test/1, seq1_test/1, seq2_test/1, seq3_test/1,
+ seq4_test/1, seq5_test/1, array1_test/1, array2_test/1,
+ enum_test/1, string1_test/1, string2_test/1, string3_test/1,
+ string4_test/1, pid_test/1, port_test/1, ref_test/1, term_test/1,
+ typedef_test/1, inline_sequence_test/1, term_sequence_test/1,
+ term_struct_test/1, wstring1_test/1]).
+
+-define(DEFAULT_TIMEOUT, 20000).
+-define(PORT_TIMEOUT, 15000).
+-define(ERLANG_SERVER_NAME, idl_erlang_server).
+-define(C_CLIENT_NODE_NAME, c_client_idl_test).
+
+%% Add/remove code path and watchdog before/after each test case.
+%%
+init_per_testcase(_Case, Config) ->
+ DataDir = ?config(data_dir, Config),
+ code:add_patha(DataDir),
+
+ %% Since other test suites use the module m_i, we have
+ %% to make sure we are using the right m_i module.
+ code:purge(m_i),
+ code:load_file(m_i),
+
+ WatchDog = test_server:timetrap(?DEFAULT_TIMEOUT),
+ [{watchdog, WatchDog}| Config].
+
+fin_per_testcase(_Case, Config) ->
+ DataDir = ?config(data_dir, Config),
+ code:del_path(DataDir),
+ WatchDog = ?config(watchdog, Config),
+ test_server:timetrap_cancel(WatchDog).
+
+all(doc) ->
+ "Test of IC with a C-client and an Erlang generic server. "
+ "The communication is via Erlang distribution.";
+all(suite) ->
+ [void_test, long_test, long_long_test, unsigned_short_test,
+ unsigned_long_test, unsigned_long_long_test, double_test,
+ char_test, wchar_test, octet_test, bool_test, struct_test,
+ struct2_test, seq1_test, seq2_test, seq3_test, seq4_test,
+ seq5_test, array1_test, array2_test, enum_test, string1_test,
+ string2_test, string3_test, string4_test, pid_test, port_test,
+ ref_test, term_test, typedef_test, inline_sequence_test,
+ term_sequence_test, term_struct_test, wstring1_test].
+
+
+array1_test(doc) -> "";
+array1_test(suite) -> [];
+array1_test(Config) ->
+ do_test(array1_test, Config).
+
+array2_test(doc) -> "";
+array2_test(suite) -> [];
+array2_test(Config) ->
+ do_test(array2_test, Config).
+
+bool_test(doc) -> "";
+bool_test(suite) -> [];
+bool_test(Config) ->
+ do_test(bool_test, Config).
+
+char_test(doc) -> "";
+char_test(suite) -> [];
+char_test(Config) ->
+ do_test(char_test, Config).
+
+double_test(doc) -> "";
+double_test(suite) -> [];
+double_test(Config) ->
+ do_test(double_test, Config).
+
+enum_test(doc) -> "";
+enum_test(suite) -> [];
+enum_test(Config) ->
+ do_test(enum_test, Config).
+
+inline_sequence_test(doc) -> "";
+inline_sequence_test(suite) -> [];
+inline_sequence_test(Config) ->
+ do_test(inline_sequence_test, Config).
+
+long_long_test(doc) -> "";
+long_long_test(suite) -> [];
+long_long_test(Config) ->
+ do_test(long_long_test, Config).
+
+long_test(doc) -> "";
+long_test(suite) -> [];
+long_test(Config) ->
+ do_test(long_test, Config).
+
+octet_test(doc) -> "";
+octet_test(suite) -> [];
+octet_test(Config) ->
+ do_test(octet_test, Config).
+
+pid_test(doc) -> "";
+pid_test(suite) -> [];
+pid_test(Config) ->
+ do_test(pid_test, Config).
+
+port_test(doc) -> "";
+port_test(suite) -> [];
+port_test(Config) ->
+ do_test(port_test, Config).
+
+ref_test(doc) -> "";
+ref_test(suite) -> [];
+ref_test(Config) ->
+ do_test(ref_test, Config).
+
+seq1_test(doc) -> "";
+seq1_test(suite) -> [];
+seq1_test(Config) ->
+ do_test(seq1_test, Config).
+
+seq2_test(doc) -> "";
+seq2_test(suite) -> [];
+seq2_test(Config) ->
+ do_test(seq2_test, Config).
+
+seq3_test(doc) -> "";
+seq3_test(suite) -> [];
+seq3_test(Config) ->
+ do_test(seq3_test, Config).
+
+seq4_test(doc) -> "";
+seq4_test(suite) -> [];
+seq4_test(Config) ->
+ do_test(seq4_test, Config).
+
+seq5_test(doc) -> "";
+seq5_test(suite) -> [];
+seq5_test(Config) ->
+ do_test(seq5_test, Config).
+
+string1_test(doc) -> "";
+string1_test(suite) -> [];
+string1_test(Config) ->
+ do_test(string1_test, Config).
+
+string2_test(doc) -> "";
+string2_test(suite) -> [];
+string2_test(Config) ->
+ do_test(string2_test, Config).
+
+string3_test(doc) -> "";
+string3_test(suite) -> [];
+string3_test(Config) ->
+ do_test(string3_test, Config).
+
+string4_test(doc) -> "";
+string4_test(suite) -> [];
+string4_test(Config) ->
+ do_test(string4_test, Config).
+
+struct2_test(doc) -> "";
+struct2_test(suite) -> [];
+struct2_test(Config) ->
+ do_test(struct2_test, Config).
+
+struct_test(doc) -> "";
+struct_test(suite) -> [];
+struct_test(Config) ->
+ do_test(struct_test, Config).
+
+term_sequence_test(doc) -> "";
+term_sequence_test(suite) -> [];
+term_sequence_test(Config) ->
+ do_test(term_sequence_test, Config).
+
+term_struct_test(doc) -> "";
+term_struct_test(suite) -> [];
+term_struct_test(Config) ->
+ do_test(term_struct_test, Config).
+
+term_test(doc) -> "";
+term_test(suite) -> [];
+term_test(Config) ->
+ do_test(term_test, Config).
+
+typedef_test(doc) -> "";
+typedef_test(suite) -> [];
+typedef_test(Config) ->
+ do_test(typedef_test, Config).
+
+unsigned_long_long_test(doc) -> "";
+unsigned_long_long_test(suite) -> [];
+unsigned_long_long_test(Config) ->
+ do_test(unsigned_long_long_test, Config).
+
+unsigned_long_test(doc) -> "";
+unsigned_long_test(suite) -> [];
+unsigned_long_test(Config) ->
+ do_test(unsigned_long_test, Config).
+
+unsigned_short_test(doc) -> "";
+unsigned_short_test(suite) -> [];
+unsigned_short_test(Config) ->
+ do_test(unsigned_short_test, Config).
+
+void_test(doc) -> "";
+void_test(suite) -> [];
+void_test(Config) ->
+ do_test(void_test, Config).
+
+wchar_test(doc) -> "";
+wchar_test(suite) -> [];
+wchar_test(Config) ->
+ do_test(wchar_test, Config).
+
+wstring1_test(doc) -> "";
+wstring1_test(suite) -> [];
+wstring1_test(Config) ->
+ do_test(wstring1_test, Config).
+
+
+%% It is here that all tests really are done.
+%%
+
+do_test(Case, Config) ->
+ %% Trap exits
+ process_flag(trap_exit, true),
+ %% Start the server
+ {ok, _Pid} = m_i:oe_create_link([], {local, ?ERLANG_SERVER_NAME}),
+ Node = atom_to_list(node()),
+ %% [NodeName, HostName] = string:tokens(Node, "@"),
+ DataDir = ?config(data_dir, Config),
+ %% io:format("~p: data directory: ~p~n", [?MODULE, DataDir]),
+ Cookie = atom_to_list(erlang:get_cookie()),
+ %% Start C-client node as a port program.
+ Cmd = filename:join([DataDir, "c_client"]) ++
+ " -this-node-name " ++ atom_to_list(?C_CLIENT_NODE_NAME) ++
+ " -peer-node " ++ Node ++
+ " -peer-process-name " ++ atom_to_list(?ERLANG_SERVER_NAME) ++
+ " -cookie " ++ Cookie ++
+ " -test-case " ++ atom_to_list(Case),
+ Port = open_port({spawn, Cmd}, [exit_status, eof, stderr_to_stdout]),
+ Res = wait_for_completion(Port),
+ %% Kill off node if there was timeout
+ case Res of
+ {error, timeout} ->
+ catch rpc:cast(?C_CLIENT_NODE_NAME, erlang, halt, [1]);
+ _ ->
+ ok
+ end,
+ process_flag(trap_exit, false),
+ catch m_i:stop(?ERLANG_SERVER_NAME),
+ ok = Res.
+
+
+%% Wait for eof *and* exit status, but return if exit status indicates
+%% an error, or we have been waiting more than PORT_TIMEOUT seconds.
+%%
+wait_for_completion(Port) ->
+ wait_for_completion(Port, 0).
+
+wait_for_completion(Port, N) when N < 2 ->
+ receive
+ {Port, {data, Bytes}} ->
+ %% Relay output
+ io:format("~s", [Bytes]),
+ wait_for_completion(Port, N);
+ {Port, {exit_status, 0}} ->
+ wait_for_completion(Port, N + 1);
+ {Port, {exit_status, Status}} ->
+ {error, Status};
+ {Port, eof} ->
+ wait_for_completion(Port, N + 1);
+ {'EXIT', Port, Reason} ->
+ io:format("Port exited with reason: ~w~n", [Reason]),
+ wait_for_completion(Port, N);
+ {'EXIT', From, Reason} ->
+ io:format("Got unexpected exit: ~p~n", [{'EXIT', From, Reason}]),
+ wait_for_completion(Port, N)
+ after ?PORT_TIMEOUT ->
+ {error, timeout}
+ end;
+wait_for_completion(_, _) ->
+ ok.
+
+
+
diff --git a/lib/ic/test/c_client_erl_server_proto_SUITE_data/Makefile.src b/lib/ic/test/c_client_erl_server_proto_SUITE_data/Makefile.src
new file mode 100644
index 0000000000..3dcd1d9387
--- /dev/null
+++ b/lib/ic/test/c_client_erl_server_proto_SUITE_data/Makefile.src
@@ -0,0 +1,146 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2003-2009. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+#
+# Makefile.src for c_client_erl_server test
+# Note: This file *must* work for both Unix and Windows
+#
+# We use both `rm' (Unix) and `del' (Windows) for removing files, but
+# with a `-' in front so that the error in not finding `rm' (`del') on
+# Windows (Unix) is ignored.
+#
+# VxWorks? XXX
+#
+
+.SUFFIXES:
+.SUFFIXES: .c .h .erl .idl @obj@ .@EMULATOR@
+
+
+# Variables from ts:
+#
+
+ERL_INCLUDE = @erl_include@
+
+IC_INCLUDE_PATH = @ic_include_path@
+IC_LIB = @ic_libpath@@DS@@ic_lib@
+
+ERL_INTERFACE_INCLUDE = @erl_interface_include@
+ERL_INTERFACE_LIB = @erl_interface_libpath@@DS@@erl_interface_lib@
+ERL_INTERFACE_EILIB = @erl_interface_libpath@@DS@@erl_interface_eilib@
+ERL_INTERFACE_THREADLIB = @erl_interface_threadlib@
+ERL_INTERFACE_SOCK_LIBS = @erl_interface_sock_libs@
+
+CC = @CC@
+## XXX Should set warning flag with a DEBUG_FLAG
+CFLAGS = @CFLAGS@ @DEFS@ -I@erl_include@ \
+ -I@ic_include_path@ -I@erl_interface_include@
+
+LD = @LD@
+LDFLAGS = @CROSSLDFLAGS@
+LIBS = $(IC_LIB) $(ERL_INTERFACE_LIB) $(ERL_INTERFACE_EILIB) \
+ $(ERL_INTERFACE_THREADLIB) @LIBS@ $(ERL_INTERFACE_SOCK_LIBS)
+ERLC = erlc
+
+# Generated C header files
+GEN_H_FILES = \
+ m.h \
+ m_i.h \
+ oe_c_erl_test.h
+
+# Generated C files
+GEN_C_FILES = \
+ m.c \
+ m_i.c \
+ oe_c_erl_test.c \
+ oe_code_m_a.c \
+ oe_code_m_arr1.c \
+ oe_code_m_arr2.c \
+ oe_code_m_arr3.c \
+ oe_code_m_aseq.c \
+ oe_code_m_b.c \
+ oe_code_m_bseq.c \
+ oe_code_m_dd.c \
+ oe_code_m_dyn.c \
+ oe_code_m_dyn_sl.c \
+ oe_code_m_es.c \
+ oe_code_m_et.c \
+ oe_code_m_etseq.c \
+ oe_code_m_fruit.c \
+ oe_code_m_lseq.c \
+ oe_code_m_s.c \
+ oe_code_m_s_sl.c \
+ oe_code_m_sarr3.c \
+ oe_code_m_simple.c \
+ oe_code_m_ssarr3.c \
+ oe_code_m_sseq.c \
+ oe_code_m_ssstr3.c \
+ oe_code_m_sstr3.c \
+ oe_code_m_str1.c \
+ oe_code_m_str3.c \
+ oe_code_m_strRec.c \
+ oe_code_m_strRec_str5.c \
+ oe_code_m_strRec_str7.c
+
+GEN_HRL_FILES = \
+ m.hrl \
+ m_i.hrl \
+ oe_c_erl_test.hrl
+
+GEN_ERL_FILES = \
+ m.erl \
+ m_arr2.erl \
+ m_arr3.erl \
+ m_i.erl \
+ m_str3.erl \
+ oe_c_erl_test.erl
+
+C_FILES = $(GEN_C_FILES) c_client.c my.c
+
+OBJS = $(C_FILES:.c=@obj@)
+
+PGMS = c_client@exe@
+
+ERL_FILES = $(GEN_ERL_FILES) m_i_impl.erl
+
+EBINS = $(ERL_FILES:.erl=.@EMULATOR@)
+
+
+all: $(PGMS) $(EBINS)
+
+clean:
+ -rm -f $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \
+ $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES)
+ -del /F /Q $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \
+ $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES)
+
+$(PGMS): $(OBJS)
+ $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
+
+$(GEN_C_FILES) $(GEN_H_FILES): c_erl_test.idl
+ $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,c_client}" \
+ "+{user_protocol,my}" c_erl_test.idl
+
+$(GEN_ERL_FILES) $(GEN_HRL_FILES): c_erl_test.idl
+ $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,erl_genserv}" c_erl_test.idl
+
+.c@obj@:
+ $(CC) -c -o $*@obj@ $(CFLAGS) $<
+
+.erl.@EMULATOR@:
+ $(ERLC) -I $(IC_INCLUDE_PATH) $<
+
diff --git a/lib/ic/test/c_client_erl_server_proto_SUITE_data/c_client.c b/lib/ic/test/c_client_erl_server_proto_SUITE_data/c_client.c
new file mode 100644
index 0000000000..f352b91fd5
--- /dev/null
+++ b/lib/ic/test/c_client_erl_server_proto_SUITE_data/c_client.c
@@ -0,0 +1,1763 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2003-2010. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+ */
+/* C-client for test of IC.
+ *
+ * TODO:
+ *
+ * 1. XXX #includes for VxWorks, Windows
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef __WIN32__
+# include <unistd.h>
+#endif
+
+#include <string.h>
+
+#ifdef __WIN32__
+# include <time.h>
+# include <sys/timeb.h>
+#elif defined VXWORKS
+#include <time.h>
+#include <sys/times.h>
+#else
+#include <sys/time.h>
+#endif
+
+#include <ctype.h>
+
+#ifdef __WIN32__
+# include <winsock2.h>
+# include <windows.h>
+#else
+# include <sys/types.h>
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <arpa/inet.h>
+# include <netdb.h>
+#endif
+
+#include "ei.h"
+#include "erl_interface.h"
+#include "m_i.h"
+
+#define HOSTNAMESZ 256
+#define NODENAMESZ 512
+
+#define INBUFSZ 10
+#define OUTBUFSZ 0
+
+#define MAXTRIES 5
+
+#define CHECK_EXCEPTION(x) \
+ if ((x)->_major != CORBA_NO_EXCEPTION) { \
+ fprintf(stderr,"\n\nException: %s\n\n", \
+ (char *)CORBA_exception_value((x))); \
+ CORBA_exception_free((x)); \
+ return -1; \
+ } \
+
+/* XXX Should free things here too! */
+#define RETURN_IF_OK(x) \
+ if ((x)) {\
+ fprintf(stdout, "ok\n");\
+ return 0;\
+ }\
+
+#define cmp_str(x,y) (!strcmp((x),(y)))
+#define cmp_wstr(x,y) (!ic_wstrcmp((x),(y)))
+
+typedef CORBA_Environment IC_Env;
+
+typedef int (*TestFunc)(IC_Env *);
+typedef struct {
+ char *name;
+ TestFunc func;
+} TestCase;
+
+static char longtext[] =
+"Introduction The IC application is an IDL compiler implemented in Erlang."
+" The IDL compiler generates client stubs and server skeletons."
+" Several back-ends are supported, and they fall into three main groups."
+" For more details on IC compiler options consult the ic(3) manual page."
+" Argument passing cases 1 Caller allocates all necessary storage,"
+" except that which may be encapsulated and managed within the parameter itself."
+" 2 The caller allocates a pointer and passes it by reference to the callee."
+" The callee sets the pointer to point to a valid instance of the parameter's type."
+" The caller is responsible for releasing the returned storage."
+" Following completion of a request, the caller is not allowed to modify any values"
+" in the returned storage. To do so the caller must first copy the returned instance"
+" into a new instance, then modify the new instance. 3 The caller allocates a"
+" pointer to an array slice which has all the same dimensions of the original"
+" array except the first, and passes it by reference to the callee. The callee sets"
+" the pointer to point to a valid instance of the array. The caller is responsible for"
+" releasing the returned storage. Following completion of a request, the caller is not"
+" allowed to modify any values in the returned storage. To do so the caller must first"
+" copy the returned instance into a new instance, then modify the new instance."
+" Generated Files Two files will be generated for each scope. One set of files will be"
+" generated for each module and each interface scope. An extra set is generated for"
+" those definitions at top level scope. One of the files is a header file(.h), and the"
+" other file is a C source code file (.c). In addition to these files a number of C"
+" source files will be generated for type encodings, they are named according to the "
+"following template: oe_code_<type>.c.";
+static char this_node[NODENAMESZ + 1];
+static char *progname;
+
+/* Test function prototypes */
+
+static int void_test(IC_Env *env);
+static int long_test(IC_Env *env);
+static int long_long_test(IC_Env *env);
+static int unsigned_short_test(IC_Env *env);
+static int unsigned_long_test(IC_Env *env);
+static int unsigned_long_long_test(IC_Env *env);
+static int double_test(IC_Env *env);
+static int char_test(IC_Env *env);
+static int wchar_test(IC_Env *env);
+static int octet_test(IC_Env *env);
+static int bool_test(IC_Env *env);
+static int struct_test(IC_Env *env);
+static int struct2_test(IC_Env *env);
+static int seq1_test(IC_Env *env);
+static int seq2_test(IC_Env *env);
+static int seq3_test(IC_Env *env);
+static int seq4_test(IC_Env *env);
+static int seq5_test(IC_Env *env);
+static int array1_test(IC_Env *env);
+static int array2_test(IC_Env *env);
+static int enum_test(IC_Env *env);
+static int string1_test(IC_Env *env);
+static int string2_test(IC_Env *env);
+static int string3_test(IC_Env *env);
+static int string4_test(IC_Env *env);
+static int pid_test(IC_Env *env);
+static int port_test(IC_Env *env);
+static int ref_test(IC_Env *env);
+static int term_test(IC_Env *env);
+static int typedef_test(IC_Env *env);
+static int inline_sequence_test(IC_Env *env);
+static int term_sequence_test(IC_Env *env);
+static int term_struct_test(IC_Env *env);
+static int wstring1_test(IC_Env *env);
+
+static TestCase test_cases[] = {
+ {"void_test", void_test},
+ {"long_test", long_test},
+ {"long_long_test", long_long_test},
+ {"unsigned_short_test", unsigned_short_test},
+ {"unsigned_long_test", unsigned_long_test},
+ {"unsigned_long_long_test", unsigned_long_long_test},
+ {"double_test", double_test},
+ {"char_test", char_test},
+ {"wchar_test", wchar_test},
+ {"octet_test", octet_test},
+ {"bool_test", bool_test},
+ {"struct_test", struct_test},
+ {"struct2_test", struct2_test},
+ {"seq1_test", seq1_test},
+ {"seq2_test", seq2_test},
+ {"seq3_test", seq3_test},
+ {"seq4_test", seq4_test},
+ {"seq5_test", seq5_test},
+ {"array1_test", array1_test},
+ {"array2_test", array2_test},
+ {"enum_test", enum_test},
+ {"string1_test", string1_test},
+ {"string2_test", string2_test},
+ {"string3_test", string3_test},
+ {"string4_test", string4_test},
+ {"pid_test", pid_test},
+ {"port_test", port_test},
+ {"ref_test", ref_test},
+ {"term_test", term_test},
+ {"typedef_test", typedef_test},
+ {"inline_sequence_test", inline_sequence_test},
+ {"term_sequence_test", term_sequence_test},
+ {"term_struct_test", term_struct_test},
+ {"wstring1_test", wstring1_test},
+ {"", NULL}
+};
+
+/* Other prototypes */
+static int cmp_aseq(m_aseq *a1, m_aseq *a2);
+static int cmp_a(m_a *a1, m_a *a2);
+static int cmp_bseq(m_bseq *b1, m_bseq *b2);
+static int cmp_b(m_b *b1, m_b *b2);
+static int cmp_lseq(m_lseq *b1, m_lseq *b2);
+static int cmp_etseq(m_etseq *b1, m_etseq *b2);
+static int cmp_et(m_et* b1, m_et *b2);
+static int cmp_es(m_es *b1, m_es *b2);
+static int cmp_arr1(m_arr1 b1, m_arr1 b2);
+static int cmp_dd(m_dd b1, m_dd b2);
+static int cmp_strRec(m_strRec *b1, m_strRec *b2);
+static int cmp_sseq(m_sseq *b1, m_sseq *b2);
+static int cmp_pid(erlang_pid *p1, erlang_pid *p2);
+static int cmp_port(erlang_port *p1, erlang_port *p2);
+static int cmp_ref(erlang_ref *p1, erlang_ref *p2);
+static int cmp_s(m_s *b1, m_s *b2);
+static int cmp_ssstr3(m_ssstr3 *b1, m_ssstr3 *b2);
+static int cmp_ssarr3(m_ssarr3 *b1, m_ssarr3 *b2);
+static int cmp_sarr3(m_sarr3 *b1, m_sarr3 *b2);
+static int cmp_arr3(m_arr3 b1, m_arr3 b2);
+
+static void print_aseq(m_aseq *a);
+static void print_a(m_a *a);
+static void print_bseq(m_bseq *b);
+static void print_lseq(m_lseq *b);
+static void print_b(m_b *b);
+static void print_etseq(m_etseq *b);
+static void print_et(m_et* b);
+static void print_es(m_es *b);
+static void print_arr1(long a[500]);
+static void print_dd(long a[2][3]);
+static void print_strRec(m_strRec* sr);
+static void print_sseq(m_sseq *b);
+static void print_pid(erlang_pid *p);
+static void print_port(erlang_port *p);
+static void print_ref(erlang_ref *p);
+static void print_term(ETERM *t);
+static void print_s(m_s *p);
+static void print_ssstr3(m_ssstr3 *b1);
+static void print_ssarr3(m_ssarr3 *b1);
+static void print_sarr3(m_sarr3 *b1);
+static void print_arr3(m_arr3 b1);
+static void print_wstr(CORBA_wchar *ws);
+
+static void free_etseq_buf(m_etseq *b);
+static void free_et(m_et* b);
+
+#ifdef __WIN32__
+typedef struct {
+ long tv_sec;
+ long tv_usec;
+} MyTimeval;
+#else
+typedef struct timeval MyTimeval;
+#endif
+static void my_gettimeofday(MyTimeval *tv);
+static void showtime(MyTimeval *start, MyTimeval *stop);
+static void usage(void);
+static void done(int r);
+
+
+
+/* main */
+
+#ifdef VXWORKS
+int client(int argc, char **argv)
+#else
+int main(int argc, char **argv)
+#endif
+{
+ struct hostent *hp;
+ erlang_pid pid;
+ MyTimeval start, stop;
+ int i, fd, ires, tres;
+ IC_Env *env;
+ int tries = 0;
+ char *this_node_name = NULL;
+ char *peer_node = NULL;
+ char *peer_process_name = NULL;
+ char *cookie = NULL;
+ char host[HOSTNAMESZ + 1];
+ TestFunc test_func = NULL;
+ TestCase *test_case;
+ char *test_case_name = NULL;
+
+#ifdef __WIN32__
+ WORD wVersionRequested;
+ WSADATA wsaData;
+
+ wVersionRequested = MAKEWORD(2, 0);
+
+ if (WSAStartup(wVersionRequested, &wsaData) != 0) {
+ fprintf(stderr, "Could not load winsock2 v2.0 compatible DLL");
+ exit(1);
+ }
+#endif
+
+ progname = argv[0];
+ host[HOSTNAMESZ] = '\0';
+ if (gethostname(host, HOSTNAMESZ) < 0) {
+ fprintf(stderr, "Can't find own hostname\n");
+ done(1);
+ }
+ if ((hp = gethostbyname(host)) == 0) {
+ fprintf(stderr, "Can't get ip address for host %s\n", host);
+ done(1);
+ }
+ for (i = 1; i < argc; i++) {
+ if (cmp_str(argv[i], "-help")) {
+ usage();
+ done(0);
+ } else if (cmp_str(argv[i], "-this-node-name")) {
+ i++;
+ this_node_name = argv[i];
+ } else if (cmp_str(argv[i], "-peer-node")) {
+ i++;
+ peer_node = argv[i];
+ } else if (cmp_str(argv[i], "-peer-process-name")) {
+ i++;
+ peer_process_name = argv[i];
+ } else if (cmp_str(argv[i], "-cookie")) {
+ i++;
+ cookie = argv[i];
+ } else if (cmp_str(argv[i], "-test-case")) {
+ i++;
+ test_case_name = argv[i];
+ } else {
+ fprintf(stderr, "Error : invalid argument \"%s\"\n", argv[i]);
+ usage();
+ done(1);
+ }
+ }
+
+ if (this_node_name == NULL || peer_node == NULL || test_case_name == NULL
+ || peer_process_name == NULL || cookie == NULL) {
+ fprintf(stderr, "Error: missing option\n");
+ usage();
+ done(1);
+ }
+
+ test_case = test_cases;
+ while (test_case->func) {
+ if (cmp_str(test_case->name, test_case_name)) {
+ test_func = test_case->func;
+ break;
+ }
+ test_case++;
+ }
+ if (test_func == NULL) {
+ fprintf(stderr, "Error: illegal test case: \"%s\"\n", test_case_name);
+ done(1);
+ }
+
+ /* Behead hostname at first dot */
+ for (i=0; host[i] != '\0'; i++) {
+ if (host[i] == '.') { host[i] = '\0'; break; }
+ }
+ sprintf(this_node, "%s@%s", this_node_name, host);
+ fprintf(stderr, "c_client: this node: \"%s\"\n", this_node);
+ fprintf(stderr, "c_client: peer node: \"%s\"\n", peer_node);
+ fprintf(stderr, "c_client: test case: \"%s\"\n", test_case_name);
+
+ fprintf(stderr, "c_client: starting\n");
+
+ /* initialize erl_interface */
+ erl_init(NULL, 0);
+
+ for (tries = 0; tries < MAXTRIES; tries++) {
+
+ /* connect to erlang node */
+
+ ires = erl_connect_xinit(host, this_node_name, this_node,
+ (struct in_addr *)*hp->h_addr_list,
+ cookie, 0);
+
+ fprintf(stderr, "c_client: erl_connect_xinit(): %d\n", ires);
+
+ fd = erl_connect(peer_node);
+ fprintf(stderr, "c_client: erl_connect(): %d\n", fd);
+
+ if (fd >= 0)
+ break;
+ fprintf(stderr, "c_client: cannot connect, retrying\n");
+ }
+ if (fd < 0) {
+ fprintf(stderr, "c_client: cannot connect, exiting\n");
+ done(1);
+ }
+ env = CORBA_Environment_alloc(INBUFSZ, OUTBUFSZ);
+ env->_fd = fd;
+ strcpy(env->_regname, peer_process_name);
+ env->_to_pid = NULL;
+ env->_from_pid = &pid;
+
+ strcpy(pid.node, this_node);
+ pid.num = fd;
+ pid.serial = 0;
+ pid.creation = 0;
+
+ my_gettimeofday(&start);
+ tres = test_func(env); /* Call test case */
+ my_gettimeofday(&stop);
+ showtime(&start, &stop);
+ erl_close_connection(fd);
+
+ printf("c_client: env->_inbuf before : %d\n", INBUFSZ);
+ printf("c_client: env->_outbuf before : %d\n", OUTBUFSZ);
+ printf("c_client: env->_inbuf after : %d\n", env->_inbufsz);
+ printf("c_client: env->_outbuf after : %d\n", env->_outbufsz);
+
+ CORBA_free(env->_inbuf);
+ CORBA_free(env->_outbuf);
+ CORBA_free(env);
+ done(tres);
+}
+
+static void usage()
+{
+ fprintf(stderr, "Usage: %s [-help] -this-node-name <name> "
+ "-peer-node <nodename> -peer-process-name <name> "
+ "-cookie <cookie> -test-case <test case name>\n", progname);
+ fprintf(stderr, "Example:\n %s -this-node-name kalle "
+ "-peer-node olle@home -peer-process-name idltest "
+ "-cookie oa678er -test-case octet_test\n", progname);
+}
+
+static void done(int r)
+{
+#ifdef __WIN32__
+ WSACleanup();
+#endif
+ exit(r);
+}
+
+
+/* TESTS */
+
+static int void_test(IC_Env *env)
+{
+ fprintf(stdout, "\n======== m_i_void test ======\n\n");
+ m_i_void_test(NULL,env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(1);
+}
+
+static int long_test(IC_Env *env)
+{
+ long l = 4711, lo, lr;
+
+ fprintf(stdout, "\n======== m_i_long test ======\n\n");
+ lr = m_i_long_test(NULL, l, &lo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(l == lo && l == lr);
+ if (l != lo)
+ fprintf(stdout, " out parameter error, sent: %ld, got: %ld\n", l, lo);
+ if (l != lr)
+ fprintf(stdout, " result error, sent: %ld, got: %ld\n", l, lr);
+ return -1;
+}
+
+static int long_long_test(IC_Env *env)
+{
+ CORBA_long_long ll = 4711, llo, llr;
+
+ fprintf(stdout, "\n======== m_i_longlong test ======\n\n");
+ llr = m_i_longlong_test(NULL, ll, &llo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(ll == llo && ll == llr);
+ if (ll != llo)
+ fprintf(stdout, " out parameter error, sent: %ld, got: %ld\n",
+ ll, llo);
+ if (ll != llr)
+ fprintf(stdout, " result error, sent: %ld, got: %ld\n", ll, llr);
+ return -1;
+}
+
+static int unsigned_short_test(IC_Env *env)
+{
+ unsigned short x, y = 2, z;
+
+ fprintf(stdout, "\n======== m_i_ushort test ======\n\n");
+ x = m_i_ushort_test(NULL, y, &z, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(y == z && y == x);
+ if (y != z)
+ fprintf(stdout, " out parameter error, sent: %d, got: %d\n", y, z);
+ if (y != x)
+ fprintf(stdout, " result error, sent: %d, got: %d\n", y, x);
+ return -1;
+}
+
+
+static int unsigned_long_test(IC_Env *env)
+{
+ unsigned long ul = 5050, ulo, ulr;
+
+ fprintf(stdout, "\n======== m_i_ulong test ======\n\n");
+ ulr = m_i_ulong_test(NULL, ul, &ulo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(ul == ulo && ul == ulr);
+ if (ul != ulo)
+ fprintf(stdout, " out parameter error, sent: %lu, got: %lu\n",
+ ul, ulo);
+ if (ul != ulr)
+ fprintf(stdout, " result error, sent: %lu, got: %lu\n", ul, ulr);
+ return -1;
+}
+
+/*
+ * Note: CORBA_unsigned_long_long is in fact a plain long.
+ */
+static int unsigned_long_long_test(IC_Env *env)
+{
+ CORBA_unsigned_long_long ull = 5050, ullo, ullr;
+
+ fprintf(stdout, "\n======== m_i_ulonglong test ======\n\n");
+ ullr = m_i_ulonglong_test(NULL, ull, &ullo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(ull == ullo && ull == ullr);
+ if (ull != ullo)
+ fprintf(stdout, " out parameter error, sent: %lu, got: %lu\n",
+ ull, ullo);
+ if (ull != ullr)
+ fprintf(stdout, " result error, sent: %lu, got: %lu\n",
+ ull, ullr);
+ return -1;
+}
+
+static int double_test(IC_Env *env)
+{
+ double d = 12.1212, db, dr;
+
+ fprintf(stdout, "\n======== m_i_double test ======\n\n");
+ dr = m_i_double_test(NULL, d, &db, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(d == db && d == dr);
+ if (d != db)
+ fprintf(stdout, " out parameter error, sent: %f, got: %f\n", d, db);
+ if (d != dr)
+ fprintf(stdout, " result error, sent: %f, got: %f\n", d, dr);
+ return -1;
+}
+
+static int char_test(IC_Env *env)
+{
+ char c = 'g', co, cr;
+
+ /* char test */
+ fprintf(stdout, "\n======== m_i_char test ======\n\n");
+ cr = m_i_char_test(NULL, c, &co, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(c == co && c == cr);
+ if (c !=co)
+ fprintf(stdout, " out parameter error, sent: %c, got: %c\n", c, co);
+ if (c != cr)
+ fprintf(stdout, " result error, sent: %c, got: %c\n", c, cr);
+ return -1;
+}
+
+static int wchar_test(IC_Env *env)
+{
+ CORBA_wchar wc = 103, wco, wcr;
+
+ fprintf(stdout, "\n======== m_i_wchar test ======\n\n");
+ wcr = m_i_wchar_test(NULL, wc, &wco, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(wc == wco && wc == wcr);
+ if (wc != wco)
+ fprintf(stdout, " out parameter error, sent: %lu, got: %lu\n",
+ wc, wco);
+ if (wc != wcr)
+ fprintf(stdout, " result error, sent: %lu, got: %lu\n",
+ wc, wcr);
+ return -1;
+}
+
+static int octet_test(IC_Env *env)
+{
+ char o ='r', oo, or;
+
+ fprintf(stdout, "\n======== m_i_octet test ======\n\n");
+ or = m_i_octet_test(NULL, o, &oo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(o == oo && o == or);
+ if (o != oo)
+ fprintf(stdout, " out parameter error, sent: %c, got: %c\n", o, oo);
+ if (o != or)
+ fprintf(stdout, " result error, sent: %c, got: %c\n", o, or);
+ return -1;
+}
+
+static int bool_test(IC_Env *env)
+{
+ unsigned char i = 0, io, ir;
+
+ fprintf(stdout, "\n======== m_i_bool test ======\n\n");
+ ir = m_i_bool_test(NULL, i, &io, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(i == io && i == ir);
+ if (i != io)
+ fprintf(stdout, " out parameter error, sent: %d, got: %d\n", i, io);
+ if (i != ir)
+ fprintf(stdout, " result error, sent: %d, got: %d\n", i, ir);
+ return -1;
+}
+
+static int struct_test(IC_Env *env)
+{
+ m_b b = {4711, 'a'}, bo, br;
+
+ fprintf(stdout, "\n======== m_i_struct test ======\n\n");
+ br = m_i_struct_test(NULL, &b, &bo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_b(&b, &bo) && cmp_b(&b, &br));
+ if (!cmp_b(&b, &bo)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_b(&b);
+ fprintf(stdout, " got:\n");
+ print_b(&bo);
+ fprintf(stdout, "\n");
+ }
+ if (!cmp_b(&b, &br)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_b(&b);
+ fprintf(stdout, " got:\n");
+ print_b(&br);
+ fprintf(stdout, "\n");
+ }
+ return -1;
+}
+
+static int struct2_test(IC_Env *env)
+{
+ m_es esi = {m_peach, 5050}, eso, esr;
+
+ fprintf(stdout, "\n======== m_i_struct2 test ======\n\n");
+ esr = m_i_struct2_test(NULL, &esi, &eso, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_es(&esi, &eso) && cmp_es(&esi, &esr));
+ if (!cmp_es(&esi, &eso)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_es(&esi);
+ fprintf(stdout, " got:\n");
+ print_es(&eso);
+ fprintf(stdout, "\n");
+ }
+ if (!cmp_es(&esi, &esr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_es(&esi);
+ fprintf(stdout, " got:\n");
+ print_es(&esr);
+ fprintf(stdout, "\n");
+ }
+ return -1;
+}
+
+
+static int seq1_test(IC_Env *env)
+{
+ m_bseq bs, *bso, *bsr;
+
+ m_b ba[3] = {{4711, 'a'}, {4712, 'b'}, {4713, 'c'}};
+ bs._length = 3;
+ bs._buffer = ba;
+
+ fprintf(stdout, "\n======== m_i_seq1 test ======\n\n");
+ bsr = m_i_seq1_test(NULL, &bs, &bso, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_bseq(&bs, bso) && cmp_bseq(&bs, bsr));
+ if (!cmp_bseq(&bs, bso)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_bseq(&bs);
+ fprintf(stdout, " got:\n");
+ print_bseq(bso);
+ fprintf(stdout, "\n");
+ }
+ if (!cmp_bseq(&bs, bsr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_bseq(&bs);
+ fprintf(stdout, " got:\n");
+ print_bseq(bsr);
+ fprintf(stdout, "\n");
+ }
+ CORBA_free(bso);
+ CORBA_free(bsr);
+ return -1;
+}
+
+static int seq2_test(IC_Env *env)
+{
+ m_b ba[3] = {{4711, 'a'}, {4712, 'b'}, {4713, 'c'}};
+ m_a a;
+ m_a aa[2];
+ m_aseq as, *aso, *asr;
+
+ a.l = 9999;
+ a.y._length = 3;
+ a.y._buffer = ba;
+ a.d = 66.89898989;
+
+ aa[0] = a;
+ aa[1] = a;
+ as._length = 2;
+ as._buffer = aa;
+
+ fprintf(stdout, "\n======== m_i_seq2 test ======\n\n");
+ asr = m_i_seq2_test(NULL, &as, &aso, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_aseq(&as, aso) && cmp_aseq(&as, asr));
+ if (!cmp_aseq(&as, aso)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_aseq(&as);
+ fprintf(stdout, " got:\n");
+ print_aseq(aso);
+ fprintf(stdout, "\n");
+ }
+ if (!cmp_aseq(&as, asr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_aseq(&as);
+ fprintf(stdout, " got:\n");
+ print_aseq(asr);
+ fprintf(stdout, "\n");
+ }
+ CORBA_free(aso);
+ CORBA_free(asr);
+ return -1;
+}
+
+static int seq3_test(IC_Env *env)
+{
+ m_lseq lsi, *lso, *lsr;
+ long al[500];
+ int i=0;
+
+ for (i = 0; i < 500; i++)
+ al[i]=i;
+ lsi._length = 500;
+ lsi._buffer = al;
+
+ fprintf(stdout, "\n======== m_i_seq3 test ======\n\n");
+ lsr = m_i_seq3_test(NULL, &lsi, &lso, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_lseq(&lsi, lso) && cmp_lseq(&lsi, lsr));
+ if (!cmp_lseq(&lsi, lso)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_lseq(&lsi);
+ fprintf(stdout, " got:\n");
+ print_lseq(lso);
+ fprintf(stdout, "\n");
+ }
+ if (!cmp_lseq(&lsi, lsr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_lseq(&lsi);
+ fprintf(stdout, " got:\n");
+ print_lseq(lsr);
+ fprintf(stdout, "\n");
+ }
+ CORBA_free(lso);
+ CORBA_free(lsr);
+ return -1;
+}
+
+static int seq4_test(IC_Env *env)
+{
+ char *stra0[3] = {"a", "long", "time"};
+ char *stra1[3] = {"ago", "there", "was"};
+ char *stra2[3] = {"a", "buggy", "compiler"};
+ m_sstr3 str3s[3] = {{3, 3, stra0}, {3, 3, stra1}, {3, 3, stra2}};
+ m_ssstr3 str3ssi = {3, 3, str3s};
+ m_ssstr3 *str3sso, *str3ssr;
+
+ fprintf(stdout, "\n======== m_i_seq4 test ======\n\n");
+ str3ssr = m_i_seq4_test(NULL, &str3ssi, &str3sso, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_ssstr3(&str3ssi, str3sso) &&
+ cmp_ssstr3(&str3ssi, str3ssr));
+ if (!cmp_ssstr3(&str3ssi, str3sso)){
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_ssstr3(&str3ssi);
+ fprintf(stdout, " got:\n");
+ print_ssstr3(str3sso);
+ fprintf(stdout, "\n");
+ }
+ if (!cmp_ssstr3(&str3ssi, str3ssr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_ssstr3(&str3ssi);
+ fprintf(stdout, " got:\n");
+ print_ssstr3(str3ssr);
+ fprintf(stdout, "\n");
+ }
+ CORBA_free(str3sso);
+ CORBA_free(str3ssr);
+ return -1;
+}
+
+static int seq5_test(IC_Env *env)
+{
+ m_arr3 arr3a[3] = {
+ {4711, 18931947, 3},
+ {4711, 18931947, 3},
+ {4711, 18931947, 3}};
+ m_sarr3 arr3sa[3] = {{3, 3, arr3a}, {3, 3, arr3a}, {3, 3, arr3a}};
+ m_ssarr3 arr3ssi = {3, 3, arr3sa};
+ m_ssarr3 *arr3sso;
+ m_ssarr3 *arr3ssr;
+
+ fprintf(stdout, "\n======== m_i_seq5 test ======\n\n");
+ arr3ssr = m_i_seq5_test(NULL, &arr3ssi, &arr3sso, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_ssarr3(&arr3ssi, arr3sso) &&
+ cmp_ssarr3(&arr3ssi, arr3ssr));
+ if (!cmp_ssarr3(&arr3ssi, arr3sso)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_ssarr3(&arr3ssi);
+ fprintf(stdout, " got:\n");
+ print_ssarr3(arr3sso);
+ fprintf(stdout, "\n");
+ }
+ if (!cmp_ssarr3(&arr3ssi, arr3ssr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_ssarr3(&arr3ssi);
+ fprintf(stdout, " got:\n");
+ print_ssarr3(arr3ssr);
+ fprintf(stdout, "\n");
+ }
+ CORBA_free(arr3sso);
+ CORBA_free(arr3ssr);
+ return -1;
+}
+
+static int array1_test(IC_Env *env)
+{
+ int i;
+ long al[500];
+ m_arr1 alo;
+ m_arr1_slice* alr;
+
+ for (i = 0; i < 500; i++)
+ al[i]=i;
+
+ fprintf(stdout, "\n======== m_i_array1 test ======\n\n");
+ alr = m_i_array1_test(NULL, al, alo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_arr1(al, alo) && cmp_arr1(al, alr));
+ if (!cmp_arr1(al, alo)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_arr1(al);
+ fprintf(stdout, " got:\n");
+ print_arr1(alo);
+ fprintf(stdout, "\n");
+ }
+ if (!cmp_arr1(al,alr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_arr1(al);
+ fprintf(stdout, " got:\n");
+ print_arr1(alr);
+ fprintf(stdout, "\n");
+ }
+ free(alo);
+ free(alr);
+ return -1;
+}
+
+static int array2_test(IC_Env *env)
+{
+ long dl[2][3] = {{11, 2, 7}, {22, 8 ,13}};
+ m_dd dlo;
+ m_dd_slice* dlr;
+
+ fprintf(stdout, "\n======== m_i_array2 test ======\n\n");
+ dlr = m_i_array2_test(NULL, dl, dlo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_dd(dl,dlo) && cmp_dd(dl,dlr));
+ if (!cmp_dd(dl,dlo)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_dd(dl);
+ fprintf(stdout, " got:\n");
+ print_dd(dlo);
+ fprintf(stdout, "\n");
+ }
+ if (!cmp_dd(dl,dlr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_dd(dl);
+ fprintf(stdout, " got:\n");
+ print_dd(dlr);
+ fprintf(stdout, "\n");
+ }
+ free(*dlr);
+ return -1;
+}
+
+static int enum_test(IC_Env *env)
+{
+ m_fruit ei = m_banana, eo, er;
+
+ fprintf(stdout, "\n======== m_i_enum test ======\n\n");
+ er = m_i_enum_test(NULL, ei, &eo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(ei == eo && ei == er);
+ if (ei != eo)
+ fprintf(stdout, " out parameter error, sent: %d, got: %d\n", ei, eo);
+ if (ei != er)
+ fprintf(stdout, " result error, sent: %d, got: %d\n", ei, er);
+ return -1;
+}
+
+static int string1_test(IC_Env *env)
+{
+ char* si = longtext;
+ char* so;
+ char* sr;
+
+ fprintf(stdout, "\n======== m_i_string1 test ======\n\n");
+ sr = m_i_string1_test(NULL, si, &so, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_str(si, so) && cmp_str(si, sr));
+ if (!cmp_str(si, so))
+ fprintf(stdout, " out parameter error, sent: %s, got: %s\n", si, so);
+ if (!cmp_str(si, sr))
+ fprintf(stdout, " result error, sent: %s, got: %s\n", si, sr);
+ CORBA_free(so);
+ CORBA_free(sr);
+ return -1;
+}
+
+static int string2_test(IC_Env *env)
+{
+ char* sa[3] = {"hello", "foo", "bar"};
+ m_sseq ssi = {3, 3, sa};
+ m_sseq *sso, *ssr;
+
+ fprintf(stdout, "\n======== m_i_string2 test ======\n\n");
+ ssr = m_i_string2_test(NULL, &ssi, &sso, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_sseq(&ssi, sso) && cmp_sseq(&ssi, sso));
+ if (!cmp_sseq(&ssi, sso)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_sseq(&ssi);
+ fprintf(stdout, "got:\n");
+ print_sseq(sso);
+ }
+ if (!cmp_sseq(&ssi, ssr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_sseq(&ssi);
+ fprintf(stdout, "got:\n");
+ print_sseq(ssr);
+ }
+ CORBA_free(sso);
+ CORBA_free(ssr);
+ return -1;
+}
+
+static int string3_test(IC_Env *env)
+{
+ char* si = longtext;
+ char* so;
+ char* sr;
+
+ fprintf(stdout, "\n======== m_i_string3 test ======\n\n");
+ sr = m_i_string3_test(NULL, si, &so, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_str(si, so) && cmp_str(si, so));
+ if (!cmp_str(si, so))
+ fprintf(stdout, " out parameter error, sent: %s, got: %s\n", si, so);
+ if (!cmp_str(si, sr))
+ fprintf(stdout, " result error, sent: %s, got: %s\n", si, sr);
+ CORBA_free(so);
+ CORBA_free(sr);
+ return -1;
+}
+
+static int string4_test(IC_Env *env)
+{
+ char as1[100] = "a string", as2[200] = "help", as3[200] = "hello there";
+ m_strRec stri = { 1, /* dd */
+ as1, /* str4 */
+ {{'a', 'k'}, {'z', 'g'}, {'n', 'q'}}, /* str7 */
+ {3, 3, "buf"}, /* str5 */
+ as2, /* str6 */
+ {'m', 'f', 'o'}, /* str8 */
+ as3, /* str9 */
+ {3, 3, "stu"} /* str10 */
+ };
+ m_strRec *stro, *strr;
+
+ fprintf(stdout, "\n======== m_i_string4 test ======\n\n");
+ strr = m_i_string4_test(NULL, &stri, &stro, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_strRec(&stri,stro) && cmp_strRec(&stri,strr));
+ if (!cmp_strRec(&stri,stro)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_strRec(&stri);
+ fprintf(stdout, " got:\n");
+ print_strRec(stro);
+ fprintf(stdout, "\n");
+ }
+ if (!cmp_strRec(&stri,strr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_strRec(&stri);
+ fprintf(stdout, " got:\n");
+ print_strRec(strr);
+ fprintf(stdout, "\n");
+ }
+ CORBA_free(stro);
+ CORBA_free(strr);
+ return -1;
+}
+
+
+static int pid_test(IC_Env *env)
+{
+ erlang_pid pid = {"", 7, 0, 0}, pido, pidr;
+
+ strcpy(pid.node, this_node), /* this currently running node */
+ fprintf(stdout, "\n======== m_i_pid test ======\n\n");
+ pidr = m_i_pid_test(NULL, &pid, &pido, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_pid(&pid, &pido) && cmp_pid(&pid, &pidr));
+ if (!cmp_pid(&pid, &pido)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_pid(&pid);
+ fprintf(stdout, "got:\n");
+ print_pid(&pido);
+ }
+ if (!cmp_pid(&pid, &pidr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_pid(&pid);
+ fprintf(stdout, "got:\n");
+ print_pid(&pidr);
+ }
+ return -1;
+}
+
+static int port_test(IC_Env *env)
+{
+ erlang_port porti = {"node", 5, 1}, porto, portr;
+
+ fprintf(stdout, "\n======== m_i_port test ======\n\n");
+ portr = m_i_port_test(NULL, &porti, &porto, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_port(&porti, &porto) && cmp_port(&porti, &portr));
+ if (!cmp_port(&porti, &porto)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_port(&porti);
+ fprintf(stdout, "got:\n");
+ print_port(&porto);
+ }
+ if (!cmp_port(&porti, &portr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_port(&porti);
+ fprintf(stdout, "got:\n");
+ print_port(&portr);
+ }
+ return -1;
+}
+
+static int ref_test(IC_Env *env)
+{
+ erlang_ref refi = { "node1", 3, {1, 2, 3}, 1},
+ refo, refr;
+
+ fprintf(stdout, "\n======== m_i_ref test ======\n\n");
+ refr = m_i_ref_test(NULL, &refi, &refo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_ref(&refi, &refo) && cmp_ref(&refi, &refr));
+ if (!cmp_ref(&refi, &refo)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_ref(&refi);
+ fprintf(stdout, "got:\n");
+ print_ref(&refo);
+ }
+ if (!cmp_ref(&refi, &refr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_ref(&refi);
+ fprintf(stdout, "got:\n");
+ print_ref(&refr);
+ }
+ return -1;
+}
+
+static int term_test(IC_Env *env)
+{
+ ETERM *ti, *to, *tr;
+
+ ti = erl_format("[{hej, 1, 23}, \"string\", {1.23, 45}]");
+
+ fprintf(stdout, "\n======== m_i_term test ======\n\n");
+ tr = m_i_term_test(NULL, ti, &to, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(erl_match(ti, to) && erl_match(ti, tr));
+ if (!erl_match(ti, to)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_term(ti);
+ fprintf(stdout, "got:\n");
+ print_term(to);
+ }
+ if (!erl_match(ti, tr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_term(ti);
+ fprintf(stdout, "got:\n");
+ print_term(tr);
+ }
+ erl_free_term(ti);
+ erl_free_term(to);
+ erl_free_term(tr);
+ return -1;
+}
+
+static int typedef_test(IC_Env *env)
+{
+ m_banan mbi, mbo; /* erlang_port */
+ m_apa mai; /* ETERM* */
+ m_apa mao = NULL;
+ long tl;
+
+ strcpy(mbi.node,"node");
+ mbi.id = 15;
+ mbi.creation = 1;
+
+ fprintf(stdout, "\n======== m_i_typedef test ======\n\n");
+ mai = erl_format("[{hej, 1, 23}, \"string\", {1.23, 45}]");
+ tl = m_i_typedef_test(NULL, mai, &mbi, &mao, &mbo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(erl_match(mai, mao) && cmp_port(&mbi, &mbo) && tl == 4711);
+ if (!erl_match(mai, mao)) {
+ fprintf(stdout, " out parameter error (term), sent:\n");
+ print_term(mai);
+ fprintf(stdout, "got:\n");
+ print_term(mao);
+ }
+ if (!cmp_port(&mbi, &mbo)) {
+ fprintf(stdout, " out parameter error (port), sent:\n");
+ print_port(&mbi);
+ fprintf(stdout, "got:\n");
+ print_port(&mbo);
+ }
+ if (tl != 4711) {
+ fprintf(stdout, " result error, sent: 4711, got %ld\n", tl);
+ }
+ erl_free_term(mai);
+ erl_free_term(mao);
+ return -1;
+}
+
+static int inline_sequence_test(IC_Env *env)
+{
+ int i;
+ long al[500];
+ m_s isi = {4711, {500, 10, al}},
+ *iso, *isr;
+
+ for (i = 0; i < 500; i++)
+ al[i]=i;
+ fprintf(stdout, "\n======== m_i_inline_sequence test ======\n\n");
+ isr = m_i_inline_sequence_test(NULL, &isi, &iso, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_s(&isi, iso) && cmp_s(&isi, isr));
+ if (!cmp_s(&isi, iso)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_s(&isi);
+ fprintf(stdout, "got:\n");
+ print_s(iso);
+ }
+ if (!cmp_s(&isi, isr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_s(&isi);
+ fprintf(stdout, "got:\n");
+ print_s(isr);
+ }
+ CORBA_free(iso);
+ CORBA_free(isr);
+ return -1;
+}
+
+static int term_sequence_test(IC_Env *env)
+{
+ ETERM* et_array[4] = {
+ erl_format("[{apa, 1, 23}, \"string\", {1.23, 45}]"),
+ erl_format("[{banan, 1, 23}, \"string\", {1.23, 45}]"),
+ erl_format("[{apelsin, 1, 23}, \"string\", {1.23, 45}]"),
+ erl_format("[{mango, 1, 23}, \"string\", {1.23, 45}]")};
+ m_etseq etsi = {4, 4, et_array}, *etso, *etsr;
+
+ fprintf(stdout, "\n======== m_i_term_sequence test ======\n\n");
+ etsr = m_i_term_sequence_test(NULL, &etsi, &etso, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_etseq(&etsi, etso) && cmp_etseq(&etsi, etsr));
+ if (!cmp_etseq(&etsi, etso)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_etseq(&etsi);
+ fprintf(stdout, "got:\n");
+ print_etseq(etso);
+ }
+ if (!cmp_etseq(&etsi, etsr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_etseq(&etsi);
+ fprintf(stdout, "got:\n");
+ print_etseq(etsr);
+ }
+ free_etseq_buf(&etsi);
+ free_etseq_buf(etso);
+ free_etseq_buf(etsr);
+ CORBA_free(etso);
+ CORBA_free(etsr);
+ return -1;
+}
+
+static int term_struct_test(IC_Env *env)
+{
+ m_et eti = { erl_format("[{hej, 1, 23}, \"string\", {1.23, 45}]"),
+ 121212 };
+ m_et eto, etr;
+
+ fprintf(stdout, "\n======== m_i_term_struct test ======\n\n");
+ etr = m_i_term_struct_test(NULL, &eti, &eto, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_et(&eti, &eto) && cmp_et(&eti, &etr));
+ if (!cmp_et(&eti, &eto)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_et(&eti);
+ fprintf(stdout, "got:\n");
+ print_et(&eto);
+ }
+ if (!cmp_et(&eti, &etr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_et(&eti);
+ fprintf(stdout, "got:\n");
+ print_et(&etr);
+ }
+ free_et(&eti);
+ free_et(&eto);
+ free_et(&etr);
+ return -1;
+}
+
+static int wstring1_test(IC_Env *env)
+{
+ CORBA_wchar wsi[] = {100, 101, 102, 103, 104, 0}, *wso, *wsr;
+
+ fprintf(stdout, "\n======== m_i_wstring1 test ======\n\n");
+ wsr = m_i_wstring1_test(NULL, wsi, &wso, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_wstr(wsi, wso) && cmp_wstr(wsi, wsr));
+ if (!cmp_wstr(wsi, wso)) {
+ fprintf(stdout, " out parameter error, sent: \n");
+ print_wstr(wsi);
+ fprintf(stdout, "got:\n");
+ print_wstr(wso);
+ }
+ if (!cmp_wstr(wsi, wsr)) {
+ fprintf(stdout, " result error, sent: \n");
+ print_wstr(wsi);
+ fprintf(stdout, "got:\n");
+ print_wstr(wsr);
+ }
+ CORBA_free(wso);
+ CORBA_free(wsr);
+ return -1;
+}
+
+/* Compare functions */
+static int cmp_aseq(m_aseq *a1, m_aseq *a2)
+{
+ int i;
+
+ if (a1->_length != a2->_length)
+ return 0;
+ for (i = 0; i < a1->_length; i++)
+ if (cmp_a(&(a1->_buffer[i]), &(a2->_buffer[i])) == 0)
+ return 0;
+ return 1;
+}
+
+static int cmp_a(m_a *a1, m_a *a2)
+{
+ return a1->l == a2->l &&
+ a1->d == a2->d &&
+ cmp_bseq(&a1->y, &a2->y);
+}
+
+static int cmp_bseq(m_bseq *b1, m_bseq *b2)
+{
+ int i;
+
+ if (b1->_length != b2->_length)
+ return 0;
+ for (i = 0; i < b1->_length; i++)
+ if (cmp_b(&(b1->_buffer[i]), &(b2->_buffer[i])) == 0)
+ return 0;
+ return 1;
+}
+
+static int cmp_b(m_b *b1, m_b *b2)
+{
+ return b1->l == b2->l && b1->c == b2->c;
+}
+
+static int cmp_lseq(m_lseq *b1, m_lseq *b2)
+{
+ int i;
+
+ if (b1->_length != b2->_length)
+ return 0;
+ for (i = 0; i < b1->_length; i++)
+ if (b1->_buffer[i] != b2->_buffer[i])
+ return 0;
+ return 1;
+}
+
+static int cmp_etseq(m_etseq *b1, m_etseq *b2)
+{
+ int i;
+
+ if (b1->_length != b2->_length)
+ return 0;
+ for (i = 0; i < b1->_length; i++)
+ if (!erl_match(b1->_buffer[i], b2->_buffer[i]))
+ return 0;
+ return 1;
+}
+
+static int cmp_et(m_et* b1, m_et *b2)
+{
+ return erl_match(b1->e, b2->e) && b1->l == b2->l;
+}
+
+static int cmp_es(m_es *b1, m_es *b2)
+{
+ return b1->f == b2->f && b1->l == b2->l;
+}
+
+static int cmp_arr1(m_arr1 b1, m_arr1 b2)
+{
+ int i;
+
+ for (i = 0; i < 500; i++)
+ if (b1[i] != b2[i])
+ return 0;
+ return 1;
+}
+
+static int cmp_dd(m_dd b1, m_dd b2)
+{
+
+ int i, j;
+
+ for (i = 0; i < 2; i++)
+ for (j = 0; j < 3; j++)
+ if (b1[i][j] != b2[i][j])
+ return 0;
+ return 1;
+}
+
+
+
+static int cmp_strRec(m_strRec *b1, m_strRec *b2)
+{
+ int i, j;
+
+ if (b1->bb != b2->bb)
+ return 0;
+ if (!cmp_str(b1->str4,b2->str4))
+ return 0;
+ if (b1->str5._length != b2->str5._length)
+ return 0;
+ for (j = 0; j < b1->str5._length; j++)
+ if (b1->str5._buffer[j] != b2->str5._buffer[j])
+ return 0;
+ if (!cmp_str(b1->str6,b2->str6))
+ return 0;
+ for (i = 0; i < 2; i++)
+ for (j = 0; j < 3; j++)
+ if (b1->str7[i][j] != b2->str7[i][j])
+ return 0;
+ for (j = 0; j < 3; j++)
+ if (b1->str8[j] != b2->str8[j])
+ return 0;
+ if (!cmp_str(b1->str9,b2->str9))
+ return 0;
+ if (b1->str10._length != b2->str10._length)
+ return 0;
+ for (j = 0; j < b1->str10._length; j++)
+ if (b1->str10._buffer[j] != b2->str10._buffer[j])
+ return 0;
+ return 1;
+}
+
+
+static int cmp_sseq(m_sseq *b1, m_sseq *b2)
+{
+ int i;
+
+ if (b1->_length != b2->_length)
+ return 0;
+ for (i = 0; i < b1->_length; i++)
+ if (!cmp_str(b1->_buffer[i], b2->_buffer[i]))
+ return 0;
+ return 1;
+}
+
+
+static int cmp_pid(erlang_pid *p1, erlang_pid *p2)
+{
+ return cmp_str(p1->node,p2-> node) &&
+ p1->num == p2->num &&
+ p1->serial == p2->serial &&
+ p1->creation == p2->creation;
+}
+
+static int cmp_port(erlang_port *p1, erlang_port *p2)
+{
+ return cmp_str(p1->node,p2-> node) && p1->id == p2->id;
+}
+
+static int cmp_ref(erlang_ref *p1, erlang_ref *p2)
+{
+ return cmp_str(p1->node, p2->node) &&
+ p1->len == p2->len &&
+ (p1->len < 1 || p1->n[0] == p2->n[0]) &&
+ (p1->len < 2 || p1->n[1] == p2->n[1]) &&
+ (p1->len < 3 || p1->n[2] == p2->n[2]);
+}
+
+static int cmp_s(m_s *b1, m_s *b2)
+{
+ int i;
+
+ if (b1->l != b2->l)
+ return 0;
+ if (b1->sl._length != b2->sl._length)
+ return 0;
+ for (i = 0; i < b1->sl._length; i++)
+ if (b1->sl._buffer[i] != b2->sl._buffer[i])
+ return 0;
+ return 1;
+}
+
+
+static int cmp_ssstr3(m_ssstr3 *b1, m_ssstr3 *b2)
+{
+ int i,j;
+
+ if (b1->_length != b2->_length)
+ return 0;
+ for (i = 0; i < b1->_length; i++) {
+ if (b1->_buffer[i]._length != b2->_buffer[i]._length)
+ return 0;
+ for (j = 0; j < b1->_buffer[i]._length; j++)
+ if (!cmp_str(b1->_buffer[i]._buffer[j],
+ b2->_buffer[i]._buffer[j]))
+ return 0;
+ }
+ return 1;
+}
+
+
+
+static int cmp_ssarr3(m_ssarr3 *b1, m_ssarr3 *b2)
+{
+ int i;
+
+ if (b1->_length != b2->_length)
+ return 0;
+ for (i = 0; i < b1->_length; i++) {
+ if (!cmp_sarr3(&b1->_buffer[i], &b2->_buffer[i]))
+ return 0;
+ }
+ return 1;
+}
+
+static int cmp_sarr3(m_sarr3 *b1, m_sarr3 *b2)
+{
+ int i;
+
+ if (b1->_length != b2->_length)
+ return 0;
+ for (i = 0; i < b1->_length; i++) {
+ if (!cmp_arr3(b1->_buffer[i], b2->_buffer[i]))
+ return 0;
+ }
+ return 1;
+}
+
+static int cmp_arr3(m_arr3 b1, m_arr3 b2)
+{
+ int i;
+
+ for (i = 0; i < sizeof(m_arr3)/sizeof(CORBA_long); i++) {
+ if (b1[i] != b2[i])
+ return 0;
+ }
+ return 1;
+}
+
+/* Print functions */
+static void print_aseq(m_aseq *a)
+{
+ int i;
+ fprintf(stdout, "\nm_aseq size: %ld --------\n", a->_length);
+ for (i = 0; i < a->_length; i++)
+ print_a(&(a->_buffer[i]));
+}
+
+static void print_a(m_a *a)
+{
+ fprintf(stdout, "\nm_a --------\n l: %ld\n d:%f\n", a->l, a->d);
+ print_bseq(&a->y);
+}
+
+static void print_bseq(m_bseq *b)
+{
+ int i;
+
+ fprintf(stdout, "\nm_bseq size: %ld --------\n",b->_length);
+ for (i = 0; i < b->_length; i++)
+ print_b(&(b->_buffer[i]));
+}
+
+static void print_lseq(m_lseq *b)
+{
+ int i;
+
+ fprintf(stdout, "\nm_lseq size: %ld --------\n",b->_length);
+ for (i = 0; i < b->_length; i++)
+ fprintf(stdout, "[%d]: %ld\n", i, b->_buffer[i]);
+}
+
+static void print_b(m_b *b)
+{
+ fprintf(stdout, "\nm_b --------\n l: %ld\n c: %c\n", b->l, b->c);
+}
+
+
+static void print_etseq(m_etseq *b)
+{
+ int i;
+
+ for (i = 0; i < b->_length; i++) {
+ fprintf(stdout, "[%d]:\n", i);
+ erl_print_term(stdout, b->_buffer[i]);
+ }
+}
+
+
+static void print_et(m_et* b)
+{
+ fprintf(stdout, "\net struct --------\n");
+ erl_print_term(stdout, b->e);
+ fprintf(stdout, "long: %ld\n", b->l);
+ fprintf(stdout, "\n--------\n");
+}
+
+static void print_es(m_es *b)
+{
+ fprintf(stdout, "\nm_es --------\n f: %d\n l: %ld\n", b->f, b->l);
+}
+
+
+static void print_arr1(long a[10])
+{
+ int i;
+
+ for (i = 0; i < 10; i++)
+ fprintf(stdout, "\n[%d]: %ld\n", i, a[i]);
+}
+
+static void print_dd(long a[2][3])
+{
+ int i, j;
+
+ fprintf(stdout, "\nlong dd[2][3] --------\n");
+ for (i = 0; i < 2; i++)
+ for (j = 0; j < 3; j++)
+ fprintf(stdout, "\n[%d][%d]: %ld\n", i, j, a[i][j]);
+}
+
+
+static void print_strRec(m_strRec* sr)
+{
+ int i, j;
+
+ fprintf(stdout, "\nboolean bb : %d\n",sr->bb);
+ fprintf(stdout, "string str4 : %s\n",sr->str4);
+ fprintf(stdout, "str7[2][3] :\n");
+ for (i = 0; i < 2; i++)
+ for (j = 0; j < 3; j++)
+ fprintf(stdout, "str7[%d][%d]: %ld\n", i, j, sr->str7[i][j]);
+ fprintf(stdout, "str5._length : %ld\n",sr->str5._length);
+ for (j = 0; j < sr->str5._length; j++)
+ fprintf(stdout, "str5._buffer[%d]: %c\n", j, sr->str5._buffer[j]);
+ fprintf(stdout, "string str6 : %s\n",sr->str6);
+ fprintf(stdout, "str8 :\n");
+ for (j = 0; j < 3; j++)
+ fprintf(stdout, "str8[%d]: %c\n", j, sr->str8[j]);
+ fprintf(stdout, "string str9 : %s\n",sr->str9);
+ fprintf(stdout, "str10._length : %ld\n",sr->str10._length);
+ for (j = 0; j < sr->str10._length; j++)
+ fprintf(stdout, "str10._buffer[%d]: %c\n", j, sr->str10._buffer[j]);
+}
+
+static void print_sseq(m_sseq *b)
+{
+ int i;
+
+ fprintf(stdout, "\nm_sseq size: %ld --------\n",b->_length);
+ for (i = 0; i < b->_length; i++)
+ fprintf(stdout, "%s\n", b->_buffer[i]);
+
+}
+
+
+static void print_pid(erlang_pid *p)
+{
+ fprintf(stdout, "\nerlang_pid --------\n node: %s\n num: %d\n "
+ "serial: %d\n creation: %d\n",
+ p->node, p->num, p->serial, p->creation);
+}
+
+static void print_port(erlang_port *p)
+{
+ fprintf(stdout, "\nerlang_port --------\n node: %s\n id: %d\n "
+ "creation: %d\n", p->node, p->id, p->creation);
+}
+
+static void print_ref(erlang_ref *p)
+{
+ fprintf(stdout, "\nerlang_ref --------\n node: %s\n len: %d\n "
+ "n[0]: %d\n n[1]: %d\n n[2]: %d\n creation: %d\n",
+ p->node, p->len, p->n[0], p->n[1], p->n[2], p->creation);
+}
+
+static void print_term(ETERM *t)
+{
+ fprintf(stdout, "\nETERM --------\n");
+ erl_print_term(stdout, t);
+ fprintf(stdout, "\n--------\n");
+}
+
+static void print_s(m_s *p)
+{
+ int i;
+
+ fprintf(stdout, "\n%ld\n", p->l);
+ for (i = 0; i < p->sl._length; i++)
+ fprintf(stdout, "\n[%d]: %ld\n", i, p->sl._buffer[i]);
+}
+
+
+static void print_ssstr3(m_ssstr3 *b1)
+{
+ int i,j;
+
+ fprintf(stdout, "\nSSSTR3 --------\n");
+ fprintf(stdout,"b1->_length = %ld\n",b1->_length);
+ for (i = 0; i < b1->_length; i++) {
+ fprintf(stdout,"\nb1->_buffer[%d]._length %ld\n",
+ i, b1->_buffer[i]._length);
+ for (j = 0; j < b1->_buffer[i]._length; j++)
+ fprintf(stdout,"b1->_buffer[%d]._buffer[%d] = %s\n",
+ i, j, b1->_buffer[i]._buffer[j]);
+ }
+ fprintf(stdout, "\n--------\n");
+}
+
+static void print_wstr(CORBA_wchar *ws)
+{
+ int i = 0;
+
+ fprintf(stdout, "\nwstr --------\n");
+ while (ws[i]) {
+ fprintf(stdout, "[%d]: %ld\n", i, ws[i]);
+ i++;
+ }
+ fprintf(stdout, "\n--------\n");
+}
+
+
+static void print_ssarr3(m_ssarr3 *b1)
+{
+ int i;
+
+ fprintf(stdout, "\nssarr3 --------\n");
+ fprintf(stdout,"length: %ld\n",b1->_length);
+ fprintf(stdout, "buffer:\n");
+ for (i = 0; i < b1->_length; i++)
+ print_sarr3(&b1->_buffer[i]);
+ fprintf(stdout, "\n--------\n");
+}
+
+static void print_sarr3(m_sarr3 *b1)
+{
+ int i;
+
+ fprintf(stdout, "\nsarr3 --------\n");
+ fprintf(stdout,"length: %ld\n",b1->_length);
+ fprintf(stdout, "buffer:\n");
+ for (i = 0; i < b1->_length; i++)
+ print_arr3(b1->_buffer[i]);
+ fprintf(stdout, "\n--------\n");
+}
+
+static void print_arr3(m_arr3 b1)
+{
+ int i;
+
+ fprintf(stdout, "\narr3 --------\n");
+ for (i = 0; i < sizeof(m_arr3)/sizeof(CORBA_long); i++)
+ fprintf(stdout, "%ld ", b1[i]);
+ fprintf(stdout, "\n--------\n");
+}
+
+static void free_etseq_buf(m_etseq *b)
+{
+ int i;
+
+ for (i = 0; i < b->_length; i++)
+ erl_free_term(b->_buffer[i]);
+}
+
+static void free_et(m_et* b)
+{
+ erl_free_term(b->e);
+}
+
+static void showtime(MyTimeval *start, MyTimeval *stop)
+{
+ MyTimeval elapsed;
+
+ elapsed.tv_sec = stop->tv_sec - start->tv_sec;
+ elapsed.tv_usec = stop->tv_usec - start->tv_usec;
+ while (elapsed.tv_usec < 0) {
+ elapsed.tv_sec -= 1;
+ elapsed.tv_usec += 1000000;
+ }
+ fprintf(stderr,"%ld.%06ld seconds\n",elapsed.tv_sec, elapsed.tv_usec);
+}
+
+static void my_gettimeofday(MyTimeval *tv)
+#ifdef __WIN32__
+#define EPOCH_JULIAN_DIFF 11644473600i64
+{
+ SYSTEMTIME t;
+ FILETIME ft;
+ LONGLONG lft;
+
+ GetSystemTime(&t);
+ SystemTimeToFileTime(&t, &ft);
+ memcpy(&lft, &ft, sizeof(lft));
+ tv->tv_usec = (long) ((lft / 10i64) % 1000000i64);
+ tv->tv_sec = (long) ((lft / 10000000i64) - EPOCH_JULIAN_DIFF);
+}
+#elif defined VXWORKS
+{
+ int rate = sysClkRateGet(); /* Ticks per second */
+ unsigned long ctick = tickGet();
+ tv->tv_sec = ctick / rate; /* secs since reboot */
+ tv->tv_usec = ((ctick - (tv->tv_sec * rate))*1000000)/rate;
+}
+#else
+{
+ gettimeofday(tv, NULL);
+}
+#endif
diff --git a/lib/ic/test/c_client_erl_server_proto_SUITE_data/c_erl_test.idl b/lib/ic/test/c_client_erl_server_proto_SUITE_data/c_erl_test.idl
new file mode 100644
index 0000000000..6d229c3ac1
--- /dev/null
+++ b/lib/ic/test/c_client_erl_server_proto_SUITE_data/c_erl_test.idl
@@ -0,0 +1,173 @@
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 2003-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+#include "erlang.idl"
+
+
+const short TestConst = 1;
+
+module m {
+
+ const short TestConst = 2;
+
+ struct b {
+ long l;
+ char c;
+ };
+
+ struct simple {
+ long l;
+ b b_t;
+ };
+
+ enum fruit {orange, banana, apple, peach, pear};
+
+ typedef sequence<long> lseq;
+
+ typedef sequence<b> bseq;
+
+ struct a {
+ long l;
+ bseq y;
+ double d;
+ };
+
+ typedef sequence<a> aseq;
+
+ typedef sequence<string> sseq;
+ typedef string str;
+ typedef long myLong;
+
+ typedef long arr1[500], dd[2][3];
+
+ typedef erlang::term apa;
+ typedef erlang::port banan;
+
+ typedef sequence<erlang::term> etseq;
+
+ struct s {
+ long l;
+ sequence<long> sl;
+ };
+
+ struct es {
+ fruit f;
+ myLong l;
+ };
+
+ struct et {
+ erlang::term e;
+ long l;
+ };
+
+
+ typedef sequence<char> str1;
+ typedef string<12> str2;
+ typedef char str3[3];
+
+ typedef sequence<string> sstr3; // sequence of string
+ typedef sequence<sstr3> ssstr3; // sequence of sequences of strings
+
+ typedef long arr3[3]; // array of long
+ typedef sequence<arr3> sarr3; // sequence of array
+ typedef sequence<sarr3> ssarr3; // sequence of sequnces of arrays of strings
+
+ struct strRec{
+ boolean bb;
+ string str4;
+ long str7[3][2];
+ sequence<char> str5;
+ string<12> str6;
+ str3 str8;
+ str2 str9;
+ str1 str10;
+ };
+
+
+ struct dyn {
+ long l;
+ sequence<long> sl;
+ };
+ typedef dyn arr2[1][2];
+
+
+ interface i {
+
+ const short TestConst = 3;
+
+ //arr2 suck(in arr2 x, out arr2 y );
+
+ ///////////////////////////////// attribute long l;
+
+ // simple types
+ void void_test();
+ long long_test(in long a, out long a1);
+ long long longlong_test(in long long a, out long long a1);
+ unsigned short ushort_test(in unsigned short a, out unsigned short a1);
+ unsigned long ulong_test(in unsigned long a, out unsigned long a1);
+ unsigned long long ulonglong_test(in unsigned long long a, out unsigned long long a1);
+ double double_test(in double a, out double a1);
+ char char_test(in char a, out char a1);
+ wchar wchar_test(in wchar a, out wchar a1);
+ octet octet_test(in octet a, out octet a1);
+ boolean bool_test(in boolean a, out boolean a1);
+
+ // Seq. and struct tests
+ b struct_test(in b a, out b a1);
+ es struct2_test(in es a, out es a1);
+ //simple struct3_test(in simple x, out simple y);
+ bseq seq1_test(in bseq a, out bseq a1);
+ aseq seq2_test(in aseq a, out aseq a1);
+ lseq seq3_test(in lseq a, out lseq a1);
+ ssstr3 seq4_test(in ssstr3 a, out ssstr3 a1);
+ ssarr3 seq5_test(in ssarr3 a, out ssarr3 a1);
+
+ // Array tests
+ arr1 array1_test(in arr1 a, out arr1 a1);
+ dd array2_test(in dd a, out dd a1);
+
+ // enum test
+ fruit enum_test(in fruit a, out fruit a1);
+
+ // string tests
+ string string1_test(in string a, out string a1);
+ wstring wstring1_test(in wstring a, out wstring a1);
+ sseq string2_test(in sseq a, out sseq a1);
+ str string3_test(in str a, out str a1);
+ strRec string4_test(in strRec a, out strRec a1);
+
+ // Special erlang types
+ erlang::pid pid_test(in erlang::pid a, out erlang::pid a1);
+ erlang::port port_test(in erlang::port a, out erlang::port a1);
+ erlang::ref ref_test(in erlang::ref a, out erlang::ref a1);
+ erlang::term term_test(in erlang::term a, out erlang::term a1);
+
+ // typedef test
+ long typedef_test(in apa a, in banan b, out apa a1, out banan b1);
+
+ // inlined seq. test
+ s inline_sequence_test(in s a, out s a1);
+
+ // term seq. test
+ etseq term_sequence_test(in etseq a, out etseq a1);
+ // term struct test
+ et term_struct_test(in et a, out et a1);
+
+ };
+
+};
diff --git a/lib/ic/test/c_client_erl_server_proto_SUITE_data/erl_server.erl b/lib/ic/test/c_client_erl_server_proto_SUITE_data/erl_server.erl
new file mode 100644
index 0000000000..09358b7cf9
--- /dev/null
+++ b/lib/ic/test/c_client_erl_server_proto_SUITE_data/erl_server.erl
@@ -0,0 +1,28 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+-module(erl_server).
+
+-export([run/0, stop/0]).
+
+run() ->
+ m_i:oe_create().
+
+stop() ->
+ gen_server:cast(cidl_test, stop).
diff --git a/lib/ic/test/c_client_erl_server_proto_SUITE_data/m_i_impl.erl b/lib/ic/test/c_client_erl_server_proto_SUITE_data/m_i_impl.erl
new file mode 100644
index 0000000000..9f231de856
--- /dev/null
+++ b/lib/ic/test/c_client_erl_server_proto_SUITE_data/m_i_impl.erl
@@ -0,0 +1,161 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+-module(m_i_impl).
+-include("m.hrl").
+
+-export([init/1, terminate/2, void_test/1, long_test/2, ushort_test/2,
+ longlong_test/2, ulong_test/2, ulonglong_test/2,
+ double_test/2, char_test/2, wchar_test/2, octet_test/2,
+ bool_test/2, struct_test/2, struct2_test/2, seq1_test/2,
+ seq2_test/2, seq3_test/2, seq4_test/2, seq5_test/2,
+ array1_test/2, array2_test/2, enum_test/2, string1_test/2,
+ string2_test/2, string3_test/2, string4_test/2, pid_test/2,
+ port_test/2, ref_test/2, term_test/2, typedef_test/3,
+ inline_sequence_test/2, '_set_l'/2, '_get_l'/1,
+ term_struct_test/2, term_sequence_test/2, wstring1_test/2]).
+
+-define(PRINTDEBUG(Case),
+ io:format("erl_server: case: ~p~n"
+ "erl_server: location: ~p~n", [Case, [?FILE, ?LINE]])).
+-define(PRINTDEBUG2(Case, Msg),
+ io:format("erl_server: case: ~p~n"
+ "erl_server: Msg: ~p~n"
+ "erl_server: location: ~p~n", [Case, Msg, [?FILE, ?LINE]])).
+
+init(Env) ->
+ {ok, []}.
+
+terminate(F, R) ->
+ ok.
+
+'_get_l'(State) ->
+ ?PRINTDEBUG("_get_l"),
+ {reply, State, State}.
+void_test(State) ->
+ ?PRINTDEBUG("void_test"),
+ {reply, ok, State}.
+
+'_set_l'(State, V) ->
+ ?PRINTDEBUG2("_set_l", V),
+ {reply, ok, V}.
+ushort_test(State, V) ->
+ ?PRINTDEBUG2("ushort_test", V),
+ {reply, {V, V}, State}.
+long_test(State, V) ->
+ ?PRINTDEBUG2("long_test", V),
+ {reply, {V, V}, State}.
+longlong_test(State, V) ->
+ ?PRINTDEBUG2("longlong_test", V),
+ {reply, {V, V}, State}.
+ulong_test(State, V) ->
+ ?PRINTDEBUG2("ulong_test", V),
+ {reply, {V, V}, State}.
+ulonglong_test(State, V) ->
+ ?PRINTDEBUG2("ulonglong_test", V),
+ {reply, {V, V}, State}.
+double_test(State, V) ->
+ ?PRINTDEBUG2("double_test", V),
+ {reply, {V, V}, State}.
+char_test(State, V) ->
+ ?PRINTDEBUG2("char_test", V),
+ {reply, {V, V}, State}.
+wchar_test(State, V) ->
+ ?PRINTDEBUG2("wchar_test", V),
+ {reply, {V, V}, State}.
+octet_test(State, V) ->
+ ?PRINTDEBUG2("octet_test", V),
+ {reply, {V, V}, State}.
+bool_test(State, V) ->
+ ?PRINTDEBUG2("bool_test", V),
+ {reply, {V, V}, State}.
+
+struct_test(State, V) ->
+ ?PRINTDEBUG2("struct_test", V),
+ {reply, {V, V}, State}.
+struct2_test(State, V) ->
+ ?PRINTDEBUG2("struct2_test", V),
+ {reply, {V, V}, State}.
+seq1_test(State, V) ->
+ ?PRINTDEBUG2("seq1_test", V),
+ {reply, {V, V}, State}.
+seq2_test(State, V) ->
+ ?PRINTDEBUG2("seq2_test", V),
+ {reply, {V, V}, State}.
+seq3_test(State, V) ->
+ ?PRINTDEBUG2("seq3_test", V),
+ {reply, {V, V}, State}.
+seq4_test(State, V) ->
+ ?PRINTDEBUG2("seq4_test", V),
+ {reply, {V, V}, State}.
+seq5_test(State, V) ->
+ ?PRINTDEBUG2("seq5_test", V),
+ {reply, {V, V}, State}.
+array1_test(State, V) ->
+ ?PRINTDEBUG2("array1_test", V),
+ {reply, {V, V}, State}.
+array2_test(State, V) ->
+ ?PRINTDEBUG2("array2_test", V),
+ {reply, {V, V}, State}.
+enum_test(State, V) ->
+ ?PRINTDEBUG2("enum_test", V),
+ {reply, {V, V}, State}.
+string1_test(State, V) ->
+ ?PRINTDEBUG2("string1_test", V),
+ {reply, {V, V}, State}.
+string2_test(State, V) ->
+ ?PRINTDEBUG2("string2_test", V),
+ {reply, {V, V}, State}.
+string3_test(State, V) ->
+ ?PRINTDEBUG2("string3_test", V),
+ {reply, {V, V}, State}.
+string4_test(State, V) ->
+ ?PRINTDEBUG2("string4_test", V),
+ {reply, {V, V}, State}.
+pid_test(State, V) ->
+ ?PRINTDEBUG2("pid_test", V),
+ {reply, {V, V}, State}.
+port_test(State, V) ->
+ ?PRINTDEBUG2("port_test", binary_to_list(term_to_binary(V))),
+ {reply, {V, V}, State}.
+ref_test(State, V) ->
+ ?PRINTDEBUG2("ref_test", binary_to_list(term_to_binary(V))),
+ {reply, {V, V}, State}.
+term_test(State, V) ->
+ ?PRINTDEBUG2("term_test", V),
+ {reply, {V, V}, State}.
+typedef_test(State, A, B) ->
+ ?PRINTDEBUG2("typedef_test", [A,B]),
+ {reply, {4711, A, B}, State}.
+inline_sequence_test(State, V) ->
+ ?PRINTDEBUG2("inline_sequence_test", V),
+ {reply, {V, V}, State}.
+term_sequence_test(State, V) ->
+ ?PRINTDEBUG2("term_sequence_test", V),
+ {reply, {V, V}, State}.
+term_struct_test(State, V) ->
+ ?PRINTDEBUG2("term_struct_test", V),
+ {reply, {V, V}, State}.
+wstring1_test(State, V) ->
+ ?PRINTDEBUG2("wstring1_test", V),
+ {reply, {V, V}, State}.
+
+
+
+
diff --git a/lib/ic/test/c_client_erl_server_proto_SUITE_data/my.c b/lib/ic/test/c_client_erl_server_proto_SUITE_data/my.c
new file mode 100644
index 0000000000..f8a3b28cc2
--- /dev/null
+++ b/lib/ic/test/c_client_erl_server_proto_SUITE_data/my.c
@@ -0,0 +1,50 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2004-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+ */
+
+#include "ic.h"
+#include "m_i.h"
+
+int my_prepare_notification_encoding(CORBA_Environment *env)
+{
+ return oe_prepare_notification_encoding(env);
+}
+
+int my_send_notification(CORBA_Environment *env)
+{
+ return oe_send_notification(env);
+}
+
+int my_prepare_request_encoding(CORBA_Environment *env)
+{
+ return oe_prepare_request_encoding(env);
+}
+
+int my_send_request_and_receive_reply(CORBA_Environment *env)
+{
+ return oe_send_request_and_receive_reply(env);
+}
+
+int my_prepare_reply_decoding(CORBA_Environment *env)
+{
+ return oe_prepare_reply_decoding(env);
+}
+
+
+
diff --git a/lib/ic/test/c_client_erl_server_proto_tmo_SUITE.erl b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE.erl
new file mode 100644
index 0000000000..595c5bf483
--- /dev/null
+++ b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE.erl
@@ -0,0 +1,315 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+
+%%----------------------------------------------------------------------
+%% Purpose : Test suite for c-client/erl-server
+%%----------------------------------------------------------------------
+
+-module(c_client_erl_server_proto_tmo_SUITE).
+-include("test_server.hrl").
+
+-export([init_per_testcase/2, fin_per_testcase/2,
+ all/1, void_test/1, long_test/1, long_long_test/1,
+ unsigned_short_test/1, unsigned_long_test/1,
+ unsigned_long_long_test/1, double_test/1, char_test/1,
+ wchar_test/1, octet_test/1, bool_test/1, struct_test/1,
+ struct2_test/1, seq1_test/1, seq2_test/1, seq3_test/1,
+ seq4_test/1, seq5_test/1, array1_test/1, array2_test/1,
+ enum_test/1, string1_test/1, string2_test/1, string3_test/1,
+ string4_test/1, pid_test/1, port_test/1, ref_test/1, term_test/1,
+ typedef_test/1, inline_sequence_test/1, term_sequence_test/1,
+ term_struct_test/1, wstring1_test/1]).
+
+-define(DEFAULT_TIMEOUT, 20000).
+-define(PORT_TIMEOUT, 15000).
+-define(ERLANG_SERVER_NAME, idl_erlang_server).
+-define(C_CLIENT_NODE_NAME, c_client_idl_test).
+
+%% Add/remove code path and watchdog before/after each test case.
+%%
+init_per_testcase(_Case, Config) ->
+ DataDir = ?config(data_dir, Config),
+ code:add_patha(DataDir),
+
+ %% Since other test suites use the module m_i, we have
+ %% to make sure we are using the right m_i module.
+ code:purge(m_i),
+ code:load_file(m_i),
+
+ WatchDog = test_server:timetrap(?DEFAULT_TIMEOUT),
+ [{watchdog, WatchDog}| Config].
+
+fin_per_testcase(_Case, Config) ->
+ DataDir = ?config(data_dir, Config),
+ code:del_path(DataDir),
+ WatchDog = ?config(watchdog, Config),
+ test_server:timetrap_cancel(WatchDog).
+
+all(doc) ->
+ "Test of IC with a C-client and an Erlang generic server. "
+ "The communication is via Erlang distribution.";
+all(suite) ->
+ [void_test, long_test, long_long_test, unsigned_short_test,
+ unsigned_long_test, unsigned_long_long_test, double_test,
+ char_test, wchar_test, octet_test, bool_test, struct_test,
+ struct2_test, seq1_test, seq2_test, seq3_test, seq4_test,
+ seq5_test, array1_test, array2_test, enum_test, string1_test,
+ string2_test, string3_test, string4_test, pid_test, port_test,
+ ref_test, term_test, typedef_test, inline_sequence_test,
+ term_sequence_test, term_struct_test, wstring1_test].
+
+
+array1_test(doc) -> "";
+array1_test(suite) -> [];
+array1_test(Config) ->
+ do_test(array1_test, Config).
+
+array2_test(doc) -> "";
+array2_test(suite) -> [];
+array2_test(Config) ->
+ do_test(array2_test, Config).
+
+bool_test(doc) -> "";
+bool_test(suite) -> [];
+bool_test(Config) ->
+ do_test(bool_test, Config).
+
+char_test(doc) -> "";
+char_test(suite) -> [];
+char_test(Config) ->
+ do_test(char_test, Config).
+
+double_test(doc) -> "";
+double_test(suite) -> [];
+double_test(Config) ->
+ do_test(double_test, Config).
+
+enum_test(doc) -> "";
+enum_test(suite) -> [];
+enum_test(Config) ->
+ do_test(enum_test, Config).
+
+inline_sequence_test(doc) -> "";
+inline_sequence_test(suite) -> [];
+inline_sequence_test(Config) ->
+ do_test(inline_sequence_test, Config).
+
+long_long_test(doc) -> "";
+long_long_test(suite) -> [];
+long_long_test(Config) ->
+ do_test(long_long_test, Config).
+
+long_test(doc) -> "";
+long_test(suite) -> [];
+long_test(Config) ->
+ do_test(long_test, Config).
+
+octet_test(doc) -> "";
+octet_test(suite) -> [];
+octet_test(Config) ->
+ do_test(octet_test, Config).
+
+pid_test(doc) -> "";
+pid_test(suite) -> [];
+pid_test(Config) ->
+ do_test(pid_test, Config).
+
+port_test(doc) -> "";
+port_test(suite) -> [];
+port_test(Config) ->
+ do_test(port_test, Config).
+
+ref_test(doc) -> "";
+ref_test(suite) -> [];
+ref_test(Config) ->
+ do_test(ref_test, Config).
+
+seq1_test(doc) -> "";
+seq1_test(suite) -> [];
+seq1_test(Config) ->
+ do_test(seq1_test, Config).
+
+seq2_test(doc) -> "";
+seq2_test(suite) -> [];
+seq2_test(Config) ->
+ do_test(seq2_test, Config).
+
+seq3_test(doc) -> "";
+seq3_test(suite) -> [];
+seq3_test(Config) ->
+ do_test(seq3_test, Config).
+
+seq4_test(doc) -> "";
+seq4_test(suite) -> [];
+seq4_test(Config) ->
+ do_test(seq4_test, Config).
+
+seq5_test(doc) -> "";
+seq5_test(suite) -> [];
+seq5_test(Config) ->
+ do_test(seq5_test, Config).
+
+string1_test(doc) -> "";
+string1_test(suite) -> [];
+string1_test(Config) ->
+ do_test(string1_test, Config).
+
+string2_test(doc) -> "";
+string2_test(suite) -> [];
+string2_test(Config) ->
+ do_test(string2_test, Config).
+
+string3_test(doc) -> "";
+string3_test(suite) -> [];
+string3_test(Config) ->
+ do_test(string3_test, Config).
+
+string4_test(doc) -> "";
+string4_test(suite) -> [];
+string4_test(Config) ->
+ do_test(string4_test, Config).
+
+struct2_test(doc) -> "";
+struct2_test(suite) -> [];
+struct2_test(Config) ->
+ do_test(struct2_test, Config).
+
+struct_test(doc) -> "";
+struct_test(suite) -> [];
+struct_test(Config) ->
+ do_test(struct_test, Config).
+
+term_sequence_test(doc) -> "";
+term_sequence_test(suite) -> [];
+term_sequence_test(Config) ->
+ do_test(term_sequence_test, Config).
+
+term_struct_test(doc) -> "";
+term_struct_test(suite) -> [];
+term_struct_test(Config) ->
+ do_test(term_struct_test, Config).
+
+term_test(doc) -> "";
+term_test(suite) -> [];
+term_test(Config) ->
+ do_test(term_test, Config).
+
+typedef_test(doc) -> "";
+typedef_test(suite) -> [];
+typedef_test(Config) ->
+ do_test(typedef_test, Config).
+
+unsigned_long_long_test(doc) -> "";
+unsigned_long_long_test(suite) -> [];
+unsigned_long_long_test(Config) ->
+ do_test(unsigned_long_long_test, Config).
+
+unsigned_long_test(doc) -> "";
+unsigned_long_test(suite) -> [];
+unsigned_long_test(Config) ->
+ do_test(unsigned_long_test, Config).
+
+unsigned_short_test(doc) -> "";
+unsigned_short_test(suite) -> [];
+unsigned_short_test(Config) ->
+ do_test(unsigned_short_test, Config).
+
+void_test(doc) -> "";
+void_test(suite) -> [];
+void_test(Config) ->
+ do_test(void_test, Config).
+
+wchar_test(doc) -> "";
+wchar_test(suite) -> [];
+wchar_test(Config) ->
+ do_test(wchar_test, Config).
+
+wstring1_test(doc) -> "";
+wstring1_test(suite) -> [];
+wstring1_test(Config) ->
+ do_test(wstring1_test, Config).
+
+
+%% It is here that all tests really are done.
+%%
+
+do_test(Case, Config) ->
+ %% Trap exits
+ process_flag(trap_exit, true),
+ %% Start the server
+ {ok, _Pid} = m_i:oe_create_link([], {local, ?ERLANG_SERVER_NAME}),
+ Node = atom_to_list(node()),
+ %% [NodeName, HostName] = string:tokens(Node, "@"),
+ DataDir = ?config(data_dir, Config),
+ %% io:format("~p: data directory: ~p~n", [?MODULE, DataDir]),
+ Cookie = atom_to_list(erlang:get_cookie()),
+ %% Start C-client node as a port program.
+ Cmd = filename:join([DataDir, "c_client"]) ++
+ " -this-node-name " ++ atom_to_list(?C_CLIENT_NODE_NAME) ++
+ " -peer-node " ++ Node ++
+ " -peer-process-name " ++ atom_to_list(?ERLANG_SERVER_NAME) ++
+ " -cookie " ++ Cookie ++
+ " -test-case " ++ atom_to_list(Case),
+ Port = open_port({spawn, Cmd}, [exit_status, eof, stderr_to_stdout]),
+ Res = wait_for_completion(Port),
+ %% Kill off node if there was timeout
+ case Res of
+ {error, timeout} ->
+ catch rpc:cast(?C_CLIENT_NODE_NAME, erlang, halt, [1]);
+ _ ->
+ ok
+ end,
+ process_flag(trap_exit, false),
+ catch m_i:stop(?ERLANG_SERVER_NAME),
+ ok = Res.
+
+
+%% Wait for eof *and* exit status, but return if exit status indicates
+%% an error, or we have been waiting more than PORT_TIMEOUT seconds.
+%%
+wait_for_completion(Port) ->
+ wait_for_completion(Port, 0).
+
+wait_for_completion(Port, N) when N < 2 ->
+ receive
+ {Port, {data, Bytes}} ->
+ %% Relay output
+ io:format("~s", [Bytes]),
+ wait_for_completion(Port, N);
+ {Port, {exit_status, 0}} ->
+ wait_for_completion(Port, N + 1);
+ {Port, {exit_status, Status}} ->
+ {error, Status};
+ {Port, eof} ->
+ wait_for_completion(Port, N + 1);
+ {'EXIT', Port, Reason} ->
+ io:format("Port exited with reason: ~w~n", [Reason]),
+ wait_for_completion(Port, N);
+ {'EXIT', From, Reason} ->
+ io:format("Got unexpected exit: ~p~n", [{'EXIT', From, Reason}]),
+ wait_for_completion(Port, N)
+ after ?PORT_TIMEOUT ->
+ {error, timeout}
+ end;
+wait_for_completion(_, _) ->
+ ok.
+
+
+
diff --git a/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/Makefile.src b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/Makefile.src
new file mode 100644
index 0000000000..62672e0b95
--- /dev/null
+++ b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/Makefile.src
@@ -0,0 +1,146 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2004-2009. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+#
+# Makefile.src for c_client_erl_server test
+# Note: This file *must* work for both Unix and Windows
+#
+# We use both `rm' (Unix) and `del' (Windows) for removing files, but
+# with a `-' in front so that the error in not finding `rm' (`del') on
+# Windows (Unix) is ignored.
+#
+# VxWorks? XXX
+#
+
+.SUFFIXES:
+.SUFFIXES: .c .h .erl .idl @obj@ .@EMULATOR@
+
+
+# Variables from ts:
+#
+
+ERL_INCLUDE = @erl_include@
+
+IC_INCLUDE_PATH = @ic_include_path@
+IC_LIB = @ic_libpath@@DS@@ic_lib@
+
+ERL_INTERFACE_INCLUDE = @erl_interface_include@
+ERL_INTERFACE_LIB = @erl_interface_libpath@@DS@@erl_interface_lib@
+ERL_INTERFACE_EILIB = @erl_interface_libpath@@DS@@erl_interface_eilib@
+ERL_INTERFACE_THREADLIB = @erl_interface_threadlib@
+ERL_INTERFACE_SOCK_LIBS = @erl_interface_sock_libs@
+
+CC = @CC@
+## XXX Should set warning flag with a DEBUG_FLAG
+CFLAGS = @CFLAGS@ @DEFS@ -I@erl_include@ \
+ -I@ic_include_path@ -I@erl_interface_include@
+
+LD = @LD@
+LDFLAGS = @CROSSLDFLAGS@
+LIBS = $(IC_LIB) $(ERL_INTERFACE_LIB) $(ERL_INTERFACE_EILIB) \
+ $(ERL_INTERFACE_THREADLIB) @LIBS@ $(ERL_INTERFACE_SOCK_LIBS)
+ERLC = erlc
+
+# Generated C header files
+GEN_H_FILES = \
+ m.h \
+ m_i.h \
+ oe_c_erl_test.h
+
+# Generated C files
+GEN_C_FILES = \
+ m.c \
+ m_i.c \
+ oe_c_erl_test.c \
+ oe_code_m_a.c \
+ oe_code_m_arr1.c \
+ oe_code_m_arr2.c \
+ oe_code_m_arr3.c \
+ oe_code_m_aseq.c \
+ oe_code_m_b.c \
+ oe_code_m_bseq.c \
+ oe_code_m_dd.c \
+ oe_code_m_dyn.c \
+ oe_code_m_dyn_sl.c \
+ oe_code_m_es.c \
+ oe_code_m_et.c \
+ oe_code_m_etseq.c \
+ oe_code_m_fruit.c \
+ oe_code_m_lseq.c \
+ oe_code_m_s.c \
+ oe_code_m_s_sl.c \
+ oe_code_m_sarr3.c \
+ oe_code_m_simple.c \
+ oe_code_m_ssarr3.c \
+ oe_code_m_sseq.c \
+ oe_code_m_ssstr3.c \
+ oe_code_m_sstr3.c \
+ oe_code_m_str1.c \
+ oe_code_m_str3.c \
+ oe_code_m_strRec.c \
+ oe_code_m_strRec_str5.c \
+ oe_code_m_strRec_str7.c
+
+GEN_HRL_FILES = \
+ m.hrl \
+ m_i.hrl \
+ oe_c_erl_test.hrl
+
+GEN_ERL_FILES = \
+ m.erl \
+ m_arr2.erl \
+ m_arr3.erl \
+ m_i.erl \
+ m_str3.erl \
+ oe_c_erl_test.erl
+
+C_FILES = $(GEN_C_FILES) c_client.c my.c
+
+OBJS = $(C_FILES:.c=@obj@)
+
+PGMS = c_client@exe@
+
+ERL_FILES = $(GEN_ERL_FILES) m_i_impl.erl
+
+EBINS = $(ERL_FILES:.erl=.@EMULATOR@)
+
+
+all: $(PGMS) $(EBINS)
+
+clean:
+ -rm -f $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \
+ $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES)
+ -del /F /Q $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \
+ $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES)
+
+$(PGMS): $(OBJS)
+ $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
+
+$(GEN_C_FILES) $(GEN_H_FILES): c_erl_test.idl
+ $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,c_client}" \
+ "+{user_protocol,my}" "+{c_timeout,{5000,5000}}" c_erl_test.idl
+
+$(GEN_ERL_FILES) $(GEN_HRL_FILES): c_erl_test.idl
+ $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,erl_genserv}" c_erl_test.idl
+
+.c@obj@:
+ $(CC) -c -o $*@obj@ $(CFLAGS) $<
+
+.erl.@EMULATOR@:
+ $(ERLC) -I $(IC_INCLUDE_PATH) $<
+
diff --git a/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/c_client.c b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/c_client.c
new file mode 100644
index 0000000000..b2c5b0c836
--- /dev/null
+++ b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/c_client.c
@@ -0,0 +1,1763 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2004-2010. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+ */
+/* C-client for test of IC.
+ *
+ * TODO:
+ *
+ * 1. XXX #includes for VxWorks, Windows
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef __WIN32__
+# include <unistd.h>
+#endif
+
+#include <string.h>
+
+#ifdef __WIN32__
+# include <time.h>
+# include <sys/timeb.h>
+#elif defined VXWORKS
+#include <time.h>
+#include <sys/times.h>
+#else
+#include <sys/time.h>
+#endif
+
+#include <ctype.h>
+
+#ifdef __WIN32__
+# include <winsock2.h>
+# include <windows.h>
+#else
+# include <sys/types.h>
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <arpa/inet.h>
+# include <netdb.h>
+#endif
+
+#include "ei.h"
+#include "erl_interface.h"
+#include "m_i.h"
+
+#define HOSTNAMESZ 256
+#define NODENAMESZ 512
+
+#define INBUFSZ 10
+#define OUTBUFSZ 0
+
+#define MAXTRIES 5
+
+#define CHECK_EXCEPTION(x) \
+ if ((x)->_major != CORBA_NO_EXCEPTION) { \
+ fprintf(stderr,"\n\nException: %s\n\n", \
+ (char *)CORBA_exception_value((x))); \
+ CORBA_exception_free((x)); \
+ return -1; \
+ } \
+
+/* XXX Should free things here too! */
+#define RETURN_IF_OK(x) \
+ if ((x)) {\
+ fprintf(stdout, "ok\n");\
+ return 0;\
+ }\
+
+#define cmp_str(x,y) (!strcmp((x),(y)))
+#define cmp_wstr(x,y) (!ic_wstrcmp((x),(y)))
+
+typedef CORBA_Environment IC_Env;
+
+typedef int (*TestFunc)(IC_Env *);
+typedef struct {
+ char *name;
+ TestFunc func;
+} TestCase;
+
+static char longtext[] =
+"Introduction The IC application is an IDL compiler implemented in Erlang."
+" The IDL compiler generates client stubs and server skeletons."
+" Several back-ends are supported, and they fall into three main groups."
+" For more details on IC compiler options consult the ic(3) manual page."
+" Argument passing cases 1 Caller allocates all necessary storage,"
+" except that which may be encapsulated and managed within the parameter itself."
+" 2 The caller allocates a pointer and passes it by reference to the callee."
+" The callee sets the pointer to point to a valid instance of the parameter's type."
+" The caller is responsible for releasing the returned storage."
+" Following completion of a request, the caller is not allowed to modify any values"
+" in the returned storage. To do so the caller must first copy the returned instance"
+" into a new instance, then modify the new instance. 3 The caller allocates a"
+" pointer to an array slice which has all the same dimensions of the original"
+" array except the first, and passes it by reference to the callee. The callee sets"
+" the pointer to point to a valid instance of the array. The caller is responsible for"
+" releasing the returned storage. Following completion of a request, the caller is not"
+" allowed to modify any values in the returned storage. To do so the caller must first"
+" copy the returned instance into a new instance, then modify the new instance."
+" Generated Files Two files will be generated for each scope. One set of files will be"
+" generated for each module and each interface scope. An extra set is generated for"
+" those definitions at top level scope. One of the files is a header file(.h), and the"
+" other file is a C source code file (.c). In addition to these files a number of C"
+" source files will be generated for type encodings, they are named according to the "
+"following template: oe_code_<type>.c.";
+static char this_node[NODENAMESZ + 1];
+static char *progname;
+
+/* Test function prototypes */
+
+static int void_test(IC_Env *env);
+static int long_test(IC_Env *env);
+static int long_long_test(IC_Env *env);
+static int unsigned_short_test(IC_Env *env);
+static int unsigned_long_test(IC_Env *env);
+static int unsigned_long_long_test(IC_Env *env);
+static int double_test(IC_Env *env);
+static int char_test(IC_Env *env);
+static int wchar_test(IC_Env *env);
+static int octet_test(IC_Env *env);
+static int bool_test(IC_Env *env);
+static int struct_test(IC_Env *env);
+static int struct2_test(IC_Env *env);
+static int seq1_test(IC_Env *env);
+static int seq2_test(IC_Env *env);
+static int seq3_test(IC_Env *env);
+static int seq4_test(IC_Env *env);
+static int seq5_test(IC_Env *env);
+static int array1_test(IC_Env *env);
+static int array2_test(IC_Env *env);
+static int enum_test(IC_Env *env);
+static int string1_test(IC_Env *env);
+static int string2_test(IC_Env *env);
+static int string3_test(IC_Env *env);
+static int string4_test(IC_Env *env);
+static int pid_test(IC_Env *env);
+static int port_test(IC_Env *env);
+static int ref_test(IC_Env *env);
+static int term_test(IC_Env *env);
+static int typedef_test(IC_Env *env);
+static int inline_sequence_test(IC_Env *env);
+static int term_sequence_test(IC_Env *env);
+static int term_struct_test(IC_Env *env);
+static int wstring1_test(IC_Env *env);
+
+static TestCase test_cases[] = {
+ {"void_test", void_test},
+ {"long_test", long_test},
+ {"long_long_test", long_long_test},
+ {"unsigned_short_test", unsigned_short_test},
+ {"unsigned_long_test", unsigned_long_test},
+ {"unsigned_long_long_test", unsigned_long_long_test},
+ {"double_test", double_test},
+ {"char_test", char_test},
+ {"wchar_test", wchar_test},
+ {"octet_test", octet_test},
+ {"bool_test", bool_test},
+ {"struct_test", struct_test},
+ {"struct2_test", struct2_test},
+ {"seq1_test", seq1_test},
+ {"seq2_test", seq2_test},
+ {"seq3_test", seq3_test},
+ {"seq4_test", seq4_test},
+ {"seq5_test", seq5_test},
+ {"array1_test", array1_test},
+ {"array2_test", array2_test},
+ {"enum_test", enum_test},
+ {"string1_test", string1_test},
+ {"string2_test", string2_test},
+ {"string3_test", string3_test},
+ {"string4_test", string4_test},
+ {"pid_test", pid_test},
+ {"port_test", port_test},
+ {"ref_test", ref_test},
+ {"term_test", term_test},
+ {"typedef_test", typedef_test},
+ {"inline_sequence_test", inline_sequence_test},
+ {"term_sequence_test", term_sequence_test},
+ {"term_struct_test", term_struct_test},
+ {"wstring1_test", wstring1_test},
+ {"", NULL}
+};
+
+/* Other prototypes */
+static int cmp_aseq(m_aseq *a1, m_aseq *a2);
+static int cmp_a(m_a *a1, m_a *a2);
+static int cmp_bseq(m_bseq *b1, m_bseq *b2);
+static int cmp_b(m_b *b1, m_b *b2);
+static int cmp_lseq(m_lseq *b1, m_lseq *b2);
+static int cmp_etseq(m_etseq *b1, m_etseq *b2);
+static int cmp_et(m_et* b1, m_et *b2);
+static int cmp_es(m_es *b1, m_es *b2);
+static int cmp_arr1(m_arr1 b1, m_arr1 b2);
+static int cmp_dd(m_dd b1, m_dd b2);
+static int cmp_strRec(m_strRec *b1, m_strRec *b2);
+static int cmp_sseq(m_sseq *b1, m_sseq *b2);
+static int cmp_pid(erlang_pid *p1, erlang_pid *p2);
+static int cmp_port(erlang_port *p1, erlang_port *p2);
+static int cmp_ref(erlang_ref *p1, erlang_ref *p2);
+static int cmp_s(m_s *b1, m_s *b2);
+static int cmp_ssstr3(m_ssstr3 *b1, m_ssstr3 *b2);
+static int cmp_ssarr3(m_ssarr3 *b1, m_ssarr3 *b2);
+static int cmp_sarr3(m_sarr3 *b1, m_sarr3 *b2);
+static int cmp_arr3(m_arr3 b1, m_arr3 b2);
+
+static void print_aseq(m_aseq *a);
+static void print_a(m_a *a);
+static void print_bseq(m_bseq *b);
+static void print_lseq(m_lseq *b);
+static void print_b(m_b *b);
+static void print_etseq(m_etseq *b);
+static void print_et(m_et* b);
+static void print_es(m_es *b);
+static void print_arr1(long a[500]);
+static void print_dd(long a[2][3]);
+static void print_strRec(m_strRec* sr);
+static void print_sseq(m_sseq *b);
+static void print_pid(erlang_pid *p);
+static void print_port(erlang_port *p);
+static void print_ref(erlang_ref *p);
+static void print_term(ETERM *t);
+static void print_s(m_s *p);
+static void print_ssstr3(m_ssstr3 *b1);
+static void print_ssarr3(m_ssarr3 *b1);
+static void print_sarr3(m_sarr3 *b1);
+static void print_arr3(m_arr3 b1);
+static void print_wstr(CORBA_wchar *ws);
+
+static void free_etseq_buf(m_etseq *b);
+static void free_et(m_et* b);
+
+#ifdef __WIN32__
+typedef struct {
+ long tv_sec;
+ long tv_usec;
+} MyTimeval;
+#else
+typedef struct timeval MyTimeval;
+#endif
+static void my_gettimeofday(MyTimeval *tv);
+static void showtime(MyTimeval *start, MyTimeval *stop);
+static void usage(void);
+static void done(int r);
+
+
+
+/* main */
+
+#ifdef VXWORKS
+int client(int argc, char **argv)
+#else
+int main(int argc, char **argv)
+#endif
+{
+ struct hostent *hp;
+ erlang_pid pid;
+ MyTimeval start, stop;
+ int i, fd, ires, tres;
+ IC_Env *env;
+ int tries = 0;
+ char *this_node_name = NULL;
+ char *peer_node = NULL;
+ char *peer_process_name = NULL;
+ char *cookie = NULL;
+ char host[HOSTNAMESZ + 1];
+ TestFunc test_func = NULL;
+ TestCase *test_case;
+ char *test_case_name = NULL;
+
+#ifdef __WIN32__
+ WORD wVersionRequested;
+ WSADATA wsaData;
+
+ wVersionRequested = MAKEWORD(2, 0);
+
+ if (WSAStartup(wVersionRequested, &wsaData) != 0) {
+ fprintf(stderr, "Could not load winsock2 v2.0 compatible DLL");
+ exit(1);
+ }
+#endif
+
+ progname = argv[0];
+ host[HOSTNAMESZ] = '\0';
+ if (gethostname(host, HOSTNAMESZ) < 0) {
+ fprintf(stderr, "Can't find own hostname\n");
+ done(1);
+ }
+ if ((hp = gethostbyname(host)) == 0) {
+ fprintf(stderr, "Can't get ip address for host %s\n", host);
+ done(1);
+ }
+ for (i = 1; i < argc; i++) {
+ if (cmp_str(argv[i], "-help")) {
+ usage();
+ done(0);
+ } else if (cmp_str(argv[i], "-this-node-name")) {
+ i++;
+ this_node_name = argv[i];
+ } else if (cmp_str(argv[i], "-peer-node")) {
+ i++;
+ peer_node = argv[i];
+ } else if (cmp_str(argv[i], "-peer-process-name")) {
+ i++;
+ peer_process_name = argv[i];
+ } else if (cmp_str(argv[i], "-cookie")) {
+ i++;
+ cookie = argv[i];
+ } else if (cmp_str(argv[i], "-test-case")) {
+ i++;
+ test_case_name = argv[i];
+ } else {
+ fprintf(stderr, "Error : invalid argument \"%s\"\n", argv[i]);
+ usage();
+ done(1);
+ }
+ }
+
+ if (this_node_name == NULL || peer_node == NULL || test_case_name == NULL
+ || peer_process_name == NULL || cookie == NULL) {
+ fprintf(stderr, "Error: missing option\n");
+ usage();
+ done(1);
+ }
+
+ test_case = test_cases;
+ while (test_case->func) {
+ if (cmp_str(test_case->name, test_case_name)) {
+ test_func = test_case->func;
+ break;
+ }
+ test_case++;
+ }
+ if (test_func == NULL) {
+ fprintf(stderr, "Error: illegal test case: \"%s\"\n", test_case_name);
+ done(1);
+ }
+
+ /* Behead hostname at first dot */
+ for (i=0; host[i] != '\0'; i++) {
+ if (host[i] == '.') { host[i] = '\0'; break; }
+ }
+ sprintf(this_node, "%s@%s", this_node_name, host);
+ fprintf(stderr, "c_client: this node: \"%s\"\n", this_node);
+ fprintf(stderr, "c_client: peer node: \"%s\"\n", peer_node);
+ fprintf(stderr, "c_client: test case: \"%s\"\n", test_case_name);
+
+ fprintf(stderr, "c_client: starting\n");
+
+ /* initialize erl_interface */
+ erl_init(NULL, 0);
+
+ for (tries = 0; tries < MAXTRIES; tries++) {
+
+ /* connect to erlang node */
+
+ ires = erl_connect_xinit(host, this_node_name, this_node,
+ (struct in_addr *)*hp->h_addr_list,
+ cookie, 0);
+
+ fprintf(stderr, "c_client: erl_connect_xinit(): %d\n", ires);
+
+ fd = erl_connect(peer_node);
+ fprintf(stderr, "c_client: erl_connect(): %d\n", fd);
+
+ if (fd >= 0)
+ break;
+ fprintf(stderr, "c_client: cannot connect, retrying\n");
+ }
+ if (fd < 0) {
+ fprintf(stderr, "c_client: cannot connect, exiting\n");
+ done(1);
+ }
+ env = CORBA_Environment_alloc(INBUFSZ, OUTBUFSZ);
+ env->_fd = fd;
+ strcpy(env->_regname, peer_process_name);
+ env->_to_pid = NULL;
+ env->_from_pid = &pid;
+
+ strcpy(pid.node, this_node);
+ pid.num = fd;
+ pid.serial = 0;
+ pid.creation = 0;
+
+ my_gettimeofday(&start);
+ tres = test_func(env); /* Call test case */
+ my_gettimeofday(&stop);
+ showtime(&start, &stop);
+ erl_close_connection(fd);
+
+ printf("c_client: env->_inbuf before : %d\n", INBUFSZ);
+ printf("c_client: env->_outbuf before : %d\n", OUTBUFSZ);
+ printf("c_client: env->_inbuf after : %d\n", env->_inbufsz);
+ printf("c_client: env->_outbuf after : %d\n", env->_outbufsz);
+
+ CORBA_free(env->_inbuf);
+ CORBA_free(env->_outbuf);
+ CORBA_free(env);
+ done(tres);
+}
+
+static void usage()
+{
+ fprintf(stderr, "Usage: %s [-help] -this-node-name <name> "
+ "-peer-node <nodename> -peer-process-name <name> "
+ "-cookie <cookie> -test-case <test case name>\n", progname);
+ fprintf(stderr, "Example:\n %s -this-node-name kalle "
+ "-peer-node olle@home -peer-process-name idltest "
+ "-cookie oa678er -test-case octet_test\n", progname);
+}
+
+static void done(int r)
+{
+#ifdef __WIN32__
+ WSACleanup();
+#endif
+ exit(r);
+}
+
+
+/* TESTS */
+
+static int void_test(IC_Env *env)
+{
+ fprintf(stdout, "\n======== m_i_void test ======\n\n");
+ m_i_void_test(NULL,env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(1);
+}
+
+static int long_test(IC_Env *env)
+{
+ long l = 4711, lo, lr;
+
+ fprintf(stdout, "\n======== m_i_long test ======\n\n");
+ lr = m_i_long_test(NULL, l, &lo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(l == lo && l == lr);
+ if (l != lo)
+ fprintf(stdout, " out parameter error, sent: %ld, got: %ld\n", l, lo);
+ if (l != lr)
+ fprintf(stdout, " result error, sent: %ld, got: %ld\n", l, lr);
+ return -1;
+}
+
+static int long_long_test(IC_Env *env)
+{
+ CORBA_long_long ll = 4711, llo, llr;
+
+ fprintf(stdout, "\n======== m_i_longlong test ======\n\n");
+ llr = m_i_longlong_test(NULL, ll, &llo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(ll == llo && ll == llr);
+ if (ll != llo)
+ fprintf(stdout, " out parameter error, sent: %ld, got: %ld\n",
+ ll, llo);
+ if (ll != llr)
+ fprintf(stdout, " result error, sent: %ld, got: %ld\n", ll, llr);
+ return -1;
+}
+
+static int unsigned_short_test(IC_Env *env)
+{
+ unsigned short x, y = 2, z;
+
+ fprintf(stdout, "\n======== m_i_ushort test ======\n\n");
+ x = m_i_ushort_test(NULL, y, &z, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(y == z && y == x);
+ if (y != z)
+ fprintf(stdout, " out parameter error, sent: %d, got: %d\n", y, z);
+ if (y != x)
+ fprintf(stdout, " result error, sent: %d, got: %d\n", y, x);
+ return -1;
+}
+
+
+static int unsigned_long_test(IC_Env *env)
+{
+ unsigned long ul = 5050, ulo, ulr;
+
+ fprintf(stdout, "\n======== m_i_ulong test ======\n\n");
+ ulr = m_i_ulong_test(NULL, ul, &ulo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(ul == ulo && ul == ulr);
+ if (ul != ulo)
+ fprintf(stdout, " out parameter error, sent: %lu, got: %lu\n",
+ ul, ulo);
+ if (ul != ulr)
+ fprintf(stdout, " result error, sent: %lu, got: %lu\n", ul, ulr);
+ return -1;
+}
+
+/*
+ * Note: CORBA_unsigned_long_long is in fact a plain long.
+ */
+static int unsigned_long_long_test(IC_Env *env)
+{
+ CORBA_unsigned_long_long ull = 5050, ullo, ullr;
+
+ fprintf(stdout, "\n======== m_i_ulonglong test ======\n\n");
+ ullr = m_i_ulonglong_test(NULL, ull, &ullo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(ull == ullo && ull == ullr);
+ if (ull != ullo)
+ fprintf(stdout, " out parameter error, sent: %lu, got: %lu\n",
+ ull, ullo);
+ if (ull != ullr)
+ fprintf(stdout, " result error, sent: %lu, got: %lu\n",
+ ull, ullr);
+ return -1;
+}
+
+static int double_test(IC_Env *env)
+{
+ double d = 12.1212, db, dr;
+
+ fprintf(stdout, "\n======== m_i_double test ======\n\n");
+ dr = m_i_double_test(NULL, d, &db, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(d == db && d == dr);
+ if (d != db)
+ fprintf(stdout, " out parameter error, sent: %f, got: %f\n", d, db);
+ if (d != dr)
+ fprintf(stdout, " result error, sent: %f, got: %f\n", d, dr);
+ return -1;
+}
+
+static int char_test(IC_Env *env)
+{
+ char c = 'g', co, cr;
+
+ /* char test */
+ fprintf(stdout, "\n======== m_i_char test ======\n\n");
+ cr = m_i_char_test(NULL, c, &co, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(c == co && c == cr);
+ if (c !=co)
+ fprintf(stdout, " out parameter error, sent: %c, got: %c\n", c, co);
+ if (c != cr)
+ fprintf(stdout, " result error, sent: %c, got: %c\n", c, cr);
+ return -1;
+}
+
+static int wchar_test(IC_Env *env)
+{
+ CORBA_wchar wc = 103, wco, wcr;
+
+ fprintf(stdout, "\n======== m_i_wchar test ======\n\n");
+ wcr = m_i_wchar_test(NULL, wc, &wco, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(wc == wco && wc == wcr);
+ if (wc != wco)
+ fprintf(stdout, " out parameter error, sent: %lu, got: %lu\n",
+ wc, wco);
+ if (wc != wcr)
+ fprintf(stdout, " result error, sent: %lu, got: %lu\n",
+ wc, wcr);
+ return -1;
+}
+
+static int octet_test(IC_Env *env)
+{
+ char o ='r', oo, or;
+
+ fprintf(stdout, "\n======== m_i_octet test ======\n\n");
+ or = m_i_octet_test(NULL, o, &oo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(o == oo && o == or);
+ if (o != oo)
+ fprintf(stdout, " out parameter error, sent: %c, got: %c\n", o, oo);
+ if (o != or)
+ fprintf(stdout, " result error, sent: %c, got: %c\n", o, or);
+ return -1;
+}
+
+static int bool_test(IC_Env *env)
+{
+ unsigned char i = 0, io, ir;
+
+ fprintf(stdout, "\n======== m_i_bool test ======\n\n");
+ ir = m_i_bool_test(NULL, i, &io, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(i == io && i == ir);
+ if (i != io)
+ fprintf(stdout, " out parameter error, sent: %d, got: %d\n", i, io);
+ if (i != ir)
+ fprintf(stdout, " result error, sent: %d, got: %d\n", i, ir);
+ return -1;
+}
+
+static int struct_test(IC_Env *env)
+{
+ m_b b = {4711, 'a'}, bo, br;
+
+ fprintf(stdout, "\n======== m_i_struct test ======\n\n");
+ br = m_i_struct_test(NULL, &b, &bo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_b(&b, &bo) && cmp_b(&b, &br));
+ if (!cmp_b(&b, &bo)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_b(&b);
+ fprintf(stdout, " got:\n");
+ print_b(&bo);
+ fprintf(stdout, "\n");
+ }
+ if (!cmp_b(&b, &br)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_b(&b);
+ fprintf(stdout, " got:\n");
+ print_b(&br);
+ fprintf(stdout, "\n");
+ }
+ return -1;
+}
+
+static int struct2_test(IC_Env *env)
+{
+ m_es esi = {m_peach, 5050}, eso, esr;
+
+ fprintf(stdout, "\n======== m_i_struct2 test ======\n\n");
+ esr = m_i_struct2_test(NULL, &esi, &eso, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_es(&esi, &eso) && cmp_es(&esi, &esr));
+ if (!cmp_es(&esi, &eso)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_es(&esi);
+ fprintf(stdout, " got:\n");
+ print_es(&eso);
+ fprintf(stdout, "\n");
+ }
+ if (!cmp_es(&esi, &esr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_es(&esi);
+ fprintf(stdout, " got:\n");
+ print_es(&esr);
+ fprintf(stdout, "\n");
+ }
+ return -1;
+}
+
+
+static int seq1_test(IC_Env *env)
+{
+ m_bseq bs, *bso, *bsr;
+
+ m_b ba[3] = {{4711, 'a'}, {4712, 'b'}, {4713, 'c'}};
+ bs._length = 3;
+ bs._buffer = ba;
+
+ fprintf(stdout, "\n======== m_i_seq1 test ======\n\n");
+ bsr = m_i_seq1_test(NULL, &bs, &bso, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_bseq(&bs, bso) && cmp_bseq(&bs, bsr));
+ if (!cmp_bseq(&bs, bso)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_bseq(&bs);
+ fprintf(stdout, " got:\n");
+ print_bseq(bso);
+ fprintf(stdout, "\n");
+ }
+ if (!cmp_bseq(&bs, bsr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_bseq(&bs);
+ fprintf(stdout, " got:\n");
+ print_bseq(bsr);
+ fprintf(stdout, "\n");
+ }
+ CORBA_free(bso);
+ CORBA_free(bsr);
+ return -1;
+}
+
+static int seq2_test(IC_Env *env)
+{
+ m_b ba[3] = {{4711, 'a'}, {4712, 'b'}, {4713, 'c'}};
+ m_a a;
+ m_a aa[2];
+ m_aseq as, *aso, *asr;
+
+ a.l = 9999;
+ a.y._length = 3;
+ a.y._buffer = ba;
+ a.d = 66.89898989;
+
+ aa[0] = a;
+ aa[1] = a;
+ as._length = 2;
+ as._buffer = aa;
+
+ fprintf(stdout, "\n======== m_i_seq2 test ======\n\n");
+ asr = m_i_seq2_test(NULL, &as, &aso, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_aseq(&as, aso) && cmp_aseq(&as, asr));
+ if (!cmp_aseq(&as, aso)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_aseq(&as);
+ fprintf(stdout, " got:\n");
+ print_aseq(aso);
+ fprintf(stdout, "\n");
+ }
+ if (!cmp_aseq(&as, asr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_aseq(&as);
+ fprintf(stdout, " got:\n");
+ print_aseq(asr);
+ fprintf(stdout, "\n");
+ }
+ CORBA_free(aso);
+ CORBA_free(asr);
+ return -1;
+}
+
+static int seq3_test(IC_Env *env)
+{
+ m_lseq lsi, *lso, *lsr;
+ long al[500];
+ int i=0;
+
+ for (i = 0; i < 500; i++)
+ al[i]=i;
+ lsi._length = 500;
+ lsi._buffer = al;
+
+ fprintf(stdout, "\n======== m_i_seq3 test ======\n\n");
+ lsr = m_i_seq3_test(NULL, &lsi, &lso, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_lseq(&lsi, lso) && cmp_lseq(&lsi, lsr));
+ if (!cmp_lseq(&lsi, lso)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_lseq(&lsi);
+ fprintf(stdout, " got:\n");
+ print_lseq(lso);
+ fprintf(stdout, "\n");
+ }
+ if (!cmp_lseq(&lsi, lsr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_lseq(&lsi);
+ fprintf(stdout, " got:\n");
+ print_lseq(lsr);
+ fprintf(stdout, "\n");
+ }
+ CORBA_free(lso);
+ CORBA_free(lsr);
+ return -1;
+}
+
+static int seq4_test(IC_Env *env)
+{
+ char *stra0[3] = {"a", "long", "time"};
+ char *stra1[3] = {"ago", "there", "was"};
+ char *stra2[3] = {"a", "buggy", "compiler"};
+ m_sstr3 str3s[3] = {{3, 3, stra0}, {3, 3, stra1}, {3, 3, stra2}};
+ m_ssstr3 str3ssi = {3, 3, str3s};
+ m_ssstr3 *str3sso, *str3ssr;
+
+ fprintf(stdout, "\n======== m_i_seq4 test ======\n\n");
+ str3ssr = m_i_seq4_test(NULL, &str3ssi, &str3sso, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_ssstr3(&str3ssi, str3sso) &&
+ cmp_ssstr3(&str3ssi, str3ssr));
+ if (!cmp_ssstr3(&str3ssi, str3sso)){
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_ssstr3(&str3ssi);
+ fprintf(stdout, " got:\n");
+ print_ssstr3(str3sso);
+ fprintf(stdout, "\n");
+ }
+ if (!cmp_ssstr3(&str3ssi, str3ssr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_ssstr3(&str3ssi);
+ fprintf(stdout, " got:\n");
+ print_ssstr3(str3ssr);
+ fprintf(stdout, "\n");
+ }
+ CORBA_free(str3sso);
+ CORBA_free(str3ssr);
+ return -1;
+}
+
+static int seq5_test(IC_Env *env)
+{
+ m_arr3 arr3a[3] = {
+ {4711, 18931947, 3},
+ {4711, 18931947, 3},
+ {4711, 18931947, 3}};
+ m_sarr3 arr3sa[3] = {{3, 3, arr3a}, {3, 3, arr3a}, {3, 3, arr3a}};
+ m_ssarr3 arr3ssi = {3, 3, arr3sa};
+ m_ssarr3 *arr3sso;
+ m_ssarr3 *arr3ssr;
+
+ fprintf(stdout, "\n======== m_i_seq5 test ======\n\n");
+ arr3ssr = m_i_seq5_test(NULL, &arr3ssi, &arr3sso, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_ssarr3(&arr3ssi, arr3sso) &&
+ cmp_ssarr3(&arr3ssi, arr3ssr));
+ if (!cmp_ssarr3(&arr3ssi, arr3sso)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_ssarr3(&arr3ssi);
+ fprintf(stdout, " got:\n");
+ print_ssarr3(arr3sso);
+ fprintf(stdout, "\n");
+ }
+ if (!cmp_ssarr3(&arr3ssi, arr3ssr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_ssarr3(&arr3ssi);
+ fprintf(stdout, " got:\n");
+ print_ssarr3(arr3ssr);
+ fprintf(stdout, "\n");
+ }
+ CORBA_free(arr3sso);
+ CORBA_free(arr3ssr);
+ return -1;
+}
+
+static int array1_test(IC_Env *env)
+{
+ int i;
+ long al[500];
+ m_arr1 alo;
+ m_arr1_slice* alr;
+
+ for (i = 0; i < 500; i++)
+ al[i]=i;
+
+ fprintf(stdout, "\n======== m_i_array1 test ======\n\n");
+ alr = m_i_array1_test(NULL, al, alo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_arr1(al, alo) && cmp_arr1(al, alr));
+ if (!cmp_arr1(al, alo)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_arr1(al);
+ fprintf(stdout, " got:\n");
+ print_arr1(alo);
+ fprintf(stdout, "\n");
+ }
+ if (!cmp_arr1(al,alr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_arr1(al);
+ fprintf(stdout, " got:\n");
+ print_arr1(alr);
+ fprintf(stdout, "\n");
+ }
+ free(alo);
+ free(alr);
+ return -1;
+}
+
+static int array2_test(IC_Env *env)
+{
+ long dl[2][3] = {{11, 2, 7}, {22, 8 ,13}};
+ m_dd dlo;
+ m_dd_slice* dlr;
+
+ fprintf(stdout, "\n======== m_i_array2 test ======\n\n");
+ dlr = m_i_array2_test(NULL, dl, dlo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_dd(dl,dlo) && cmp_dd(dl,dlr));
+ if (!cmp_dd(dl,dlo)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_dd(dl);
+ fprintf(stdout, " got:\n");
+ print_dd(dlo);
+ fprintf(stdout, "\n");
+ }
+ if (!cmp_dd(dl,dlr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_dd(dl);
+ fprintf(stdout, " got:\n");
+ print_dd(dlr);
+ fprintf(stdout, "\n");
+ }
+ free(*dlr);
+ return -1;
+}
+
+static int enum_test(IC_Env *env)
+{
+ m_fruit ei = m_banana, eo, er;
+
+ fprintf(stdout, "\n======== m_i_enum test ======\n\n");
+ er = m_i_enum_test(NULL, ei, &eo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(ei == eo && ei == er);
+ if (ei != eo)
+ fprintf(stdout, " out parameter error, sent: %d, got: %d\n", ei, eo);
+ if (ei != er)
+ fprintf(stdout, " result error, sent: %d, got: %d\n", ei, er);
+ return -1;
+}
+
+static int string1_test(IC_Env *env)
+{
+ char* si = longtext;
+ char* so;
+ char* sr;
+
+ fprintf(stdout, "\n======== m_i_string1 test ======\n\n");
+ sr = m_i_string1_test(NULL, si, &so, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_str(si, so) && cmp_str(si, sr));
+ if (!cmp_str(si, so))
+ fprintf(stdout, " out parameter error, sent: %s, got: %s\n", si, so);
+ if (!cmp_str(si, sr))
+ fprintf(stdout, " result error, sent: %s, got: %s\n", si, sr);
+ CORBA_free(so);
+ CORBA_free(sr);
+ return -1;
+}
+
+static int string2_test(IC_Env *env)
+{
+ char* sa[3] = {"hello", "foo", "bar"};
+ m_sseq ssi = {3, 3, sa};
+ m_sseq *sso, *ssr;
+
+ fprintf(stdout, "\n======== m_i_string2 test ======\n\n");
+ ssr = m_i_string2_test(NULL, &ssi, &sso, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_sseq(&ssi, sso) && cmp_sseq(&ssi, sso));
+ if (!cmp_sseq(&ssi, sso)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_sseq(&ssi);
+ fprintf(stdout, "got:\n");
+ print_sseq(sso);
+ }
+ if (!cmp_sseq(&ssi, ssr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_sseq(&ssi);
+ fprintf(stdout, "got:\n");
+ print_sseq(ssr);
+ }
+ CORBA_free(sso);
+ CORBA_free(ssr);
+ return -1;
+}
+
+static int string3_test(IC_Env *env)
+{
+ char* si = longtext;
+ char* so;
+ char* sr;
+
+ fprintf(stdout, "\n======== m_i_string3 test ======\n\n");
+ sr = m_i_string3_test(NULL, si, &so, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_str(si, so) && cmp_str(si, so));
+ if (!cmp_str(si, so))
+ fprintf(stdout, " out parameter error, sent: %s, got: %s\n", si, so);
+ if (!cmp_str(si, sr))
+ fprintf(stdout, " result error, sent: %s, got: %s\n", si, sr);
+ CORBA_free(so);
+ CORBA_free(sr);
+ return -1;
+}
+
+static int string4_test(IC_Env *env)
+{
+ char as1[100] = "a string", as2[200] = "help", as3[200] = "hello there";
+ m_strRec stri = { 1, /* dd */
+ as1, /* str4 */
+ {{'a', 'k'}, {'z', 'g'}, {'n', 'q'}}, /* str7 */
+ {3, 3, "buf"}, /* str5 */
+ as2, /* str6 */
+ {'m', 'f', 'o'}, /* str8 */
+ as3, /* str9 */
+ {3, 3, "stu"} /* str10 */
+ };
+ m_strRec *stro, *strr;
+
+ fprintf(stdout, "\n======== m_i_string4 test ======\n\n");
+ strr = m_i_string4_test(NULL, &stri, &stro, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_strRec(&stri,stro) && cmp_strRec(&stri,strr));
+ if (!cmp_strRec(&stri,stro)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_strRec(&stri);
+ fprintf(stdout, " got:\n");
+ print_strRec(stro);
+ fprintf(stdout, "\n");
+ }
+ if (!cmp_strRec(&stri,strr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_strRec(&stri);
+ fprintf(stdout, " got:\n");
+ print_strRec(strr);
+ fprintf(stdout, "\n");
+ }
+ CORBA_free(stro);
+ CORBA_free(strr);
+ return -1;
+}
+
+
+static int pid_test(IC_Env *env)
+{
+ erlang_pid pid = {"", 7, 0, 0}, pido, pidr;
+
+ strcpy(pid.node, this_node), /* this currently running node */
+ fprintf(stdout, "\n======== m_i_pid test ======\n\n");
+ pidr = m_i_pid_test(NULL, &pid, &pido, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_pid(&pid, &pido) && cmp_pid(&pid, &pidr));
+ if (!cmp_pid(&pid, &pido)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_pid(&pid);
+ fprintf(stdout, "got:\n");
+ print_pid(&pido);
+ }
+ if (!cmp_pid(&pid, &pidr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_pid(&pid);
+ fprintf(stdout, "got:\n");
+ print_pid(&pidr);
+ }
+ return -1;
+}
+
+static int port_test(IC_Env *env)
+{
+ erlang_port porti = {"node", 5, 1}, porto, portr;
+
+ fprintf(stdout, "\n======== m_i_port test ======\n\n");
+ portr = m_i_port_test(NULL, &porti, &porto, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_port(&porti, &porto) && cmp_port(&porti, &portr));
+ if (!cmp_port(&porti, &porto)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_port(&porti);
+ fprintf(stdout, "got:\n");
+ print_port(&porto);
+ }
+ if (!cmp_port(&porti, &portr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_port(&porti);
+ fprintf(stdout, "got:\n");
+ print_port(&portr);
+ }
+ return -1;
+}
+
+static int ref_test(IC_Env *env)
+{
+ erlang_ref refi = { "node1", 3, {1, 2, 3}, 1},
+ refo, refr;
+
+ fprintf(stdout, "\n======== m_i_ref test ======\n\n");
+ refr = m_i_ref_test(NULL, &refi, &refo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_ref(&refi, &refo) && cmp_ref(&refi, &refr));
+ if (!cmp_ref(&refi, &refo)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_ref(&refi);
+ fprintf(stdout, "got:\n");
+ print_ref(&refo);
+ }
+ if (!cmp_ref(&refi, &refr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_ref(&refi);
+ fprintf(stdout, "got:\n");
+ print_ref(&refr);
+ }
+ return -1;
+}
+
+static int term_test(IC_Env *env)
+{
+ ETERM *ti, *to, *tr;
+
+ ti = erl_format("[{hej, 1, 23}, \"string\", {1.23, 45}]");
+
+ fprintf(stdout, "\n======== m_i_term test ======\n\n");
+ tr = m_i_term_test(NULL, ti, &to, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(erl_match(ti, to) && erl_match(ti, tr));
+ if (!erl_match(ti, to)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_term(ti);
+ fprintf(stdout, "got:\n");
+ print_term(to);
+ }
+ if (!erl_match(ti, tr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_term(ti);
+ fprintf(stdout, "got:\n");
+ print_term(tr);
+ }
+ erl_free_term(ti);
+ erl_free_term(to);
+ erl_free_term(tr);
+ return -1;
+}
+
+static int typedef_test(IC_Env *env)
+{
+ m_banan mbi, mbo; /* erlang_port */
+ m_apa mai; /* ETERM* */
+ m_apa mao = NULL;
+ long tl;
+
+ strcpy(mbi.node,"node");
+ mbi.id = 15;
+ mbi.creation = 1;
+
+ fprintf(stdout, "\n======== m_i_typedef test ======\n\n");
+ mai = erl_format("[{hej, 1, 23}, \"string\", {1.23, 45}]");
+ tl = m_i_typedef_test(NULL, mai, &mbi, &mao, &mbo, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(erl_match(mai, mao) && cmp_port(&mbi, &mbo) && tl == 4711);
+ if (!erl_match(mai, mao)) {
+ fprintf(stdout, " out parameter error (term), sent:\n");
+ print_term(mai);
+ fprintf(stdout, "got:\n");
+ print_term(mao);
+ }
+ if (!cmp_port(&mbi, &mbo)) {
+ fprintf(stdout, " out parameter error (port), sent:\n");
+ print_port(&mbi);
+ fprintf(stdout, "got:\n");
+ print_port(&mbo);
+ }
+ if (tl != 4711) {
+ fprintf(stdout, " result error, sent: 4711, got %ld\n", tl);
+ }
+ erl_free_term(mai);
+ erl_free_term(mao);
+ return -1;
+}
+
+static int inline_sequence_test(IC_Env *env)
+{
+ int i;
+ long al[500];
+ m_s isi = {4711, {500, 10, al}},
+ *iso, *isr;
+
+ for (i = 0; i < 500; i++)
+ al[i]=i;
+ fprintf(stdout, "\n======== m_i_inline_sequence test ======\n\n");
+ isr = m_i_inline_sequence_test(NULL, &isi, &iso, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_s(&isi, iso) && cmp_s(&isi, isr));
+ if (!cmp_s(&isi, iso)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_s(&isi);
+ fprintf(stdout, "got:\n");
+ print_s(iso);
+ }
+ if (!cmp_s(&isi, isr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_s(&isi);
+ fprintf(stdout, "got:\n");
+ print_s(isr);
+ }
+ CORBA_free(iso);
+ CORBA_free(isr);
+ return -1;
+}
+
+static int term_sequence_test(IC_Env *env)
+{
+ ETERM* et_array[4] = {
+ erl_format("[{apa, 1, 23}, \"string\", {1.23, 45}]"),
+ erl_format("[{banan, 1, 23}, \"string\", {1.23, 45}]"),
+ erl_format("[{apelsin, 1, 23}, \"string\", {1.23, 45}]"),
+ erl_format("[{mango, 1, 23}, \"string\", {1.23, 45}]")};
+ m_etseq etsi = {4, 4, et_array}, *etso, *etsr;
+
+ fprintf(stdout, "\n======== m_i_term_sequence test ======\n\n");
+ etsr = m_i_term_sequence_test(NULL, &etsi, &etso, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_etseq(&etsi, etso) && cmp_etseq(&etsi, etsr));
+ if (!cmp_etseq(&etsi, etso)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_etseq(&etsi);
+ fprintf(stdout, "got:\n");
+ print_etseq(etso);
+ }
+ if (!cmp_etseq(&etsi, etsr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_etseq(&etsi);
+ fprintf(stdout, "got:\n");
+ print_etseq(etsr);
+ }
+ free_etseq_buf(&etsi);
+ free_etseq_buf(etso);
+ free_etseq_buf(etsr);
+ CORBA_free(etso);
+ CORBA_free(etsr);
+ return -1;
+}
+
+static int term_struct_test(IC_Env *env)
+{
+ m_et eti = { erl_format("[{hej, 1, 23}, \"string\", {1.23, 45}]"),
+ 121212 };
+ m_et eto, etr;
+
+ fprintf(stdout, "\n======== m_i_term_struct test ======\n\n");
+ etr = m_i_term_struct_test(NULL, &eti, &eto, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_et(&eti, &eto) && cmp_et(&eti, &etr));
+ if (!cmp_et(&eti, &eto)) {
+ fprintf(stdout, " out parameter error, sent:\n");
+ print_et(&eti);
+ fprintf(stdout, "got:\n");
+ print_et(&eto);
+ }
+ if (!cmp_et(&eti, &etr)) {
+ fprintf(stdout, " result error, sent:\n");
+ print_et(&eti);
+ fprintf(stdout, "got:\n");
+ print_et(&etr);
+ }
+ free_et(&eti);
+ free_et(&eto);
+ free_et(&etr);
+ return -1;
+}
+
+static int wstring1_test(IC_Env *env)
+{
+ CORBA_wchar wsi[] = {100, 101, 102, 103, 104, 0}, *wso, *wsr;
+
+ fprintf(stdout, "\n======== m_i_wstring1 test ======\n\n");
+ wsr = m_i_wstring1_test(NULL, wsi, &wso, env);
+ CHECK_EXCEPTION(env);
+ RETURN_IF_OK(cmp_wstr(wsi, wso) && cmp_wstr(wsi, wsr));
+ if (!cmp_wstr(wsi, wso)) {
+ fprintf(stdout, " out parameter error, sent: \n");
+ print_wstr(wsi);
+ fprintf(stdout, "got:\n");
+ print_wstr(wso);
+ }
+ if (!cmp_wstr(wsi, wsr)) {
+ fprintf(stdout, " result error, sent: \n");
+ print_wstr(wsi);
+ fprintf(stdout, "got:\n");
+ print_wstr(wsr);
+ }
+ CORBA_free(wso);
+ CORBA_free(wsr);
+ return -1;
+}
+
+/* Compare functions */
+static int cmp_aseq(m_aseq *a1, m_aseq *a2)
+{
+ int i;
+
+ if (a1->_length != a2->_length)
+ return 0;
+ for (i = 0; i < a1->_length; i++)
+ if (cmp_a(&(a1->_buffer[i]), &(a2->_buffer[i])) == 0)
+ return 0;
+ return 1;
+}
+
+static int cmp_a(m_a *a1, m_a *a2)
+{
+ return a1->l == a2->l &&
+ a1->d == a2->d &&
+ cmp_bseq(&a1->y, &a2->y);
+}
+
+static int cmp_bseq(m_bseq *b1, m_bseq *b2)
+{
+ int i;
+
+ if (b1->_length != b2->_length)
+ return 0;
+ for (i = 0; i < b1->_length; i++)
+ if (cmp_b(&(b1->_buffer[i]), &(b2->_buffer[i])) == 0)
+ return 0;
+ return 1;
+}
+
+static int cmp_b(m_b *b1, m_b *b2)
+{
+ return b1->l == b2->l && b1->c == b2->c;
+}
+
+static int cmp_lseq(m_lseq *b1, m_lseq *b2)
+{
+ int i;
+
+ if (b1->_length != b2->_length)
+ return 0;
+ for (i = 0; i < b1->_length; i++)
+ if (b1->_buffer[i] != b2->_buffer[i])
+ return 0;
+ return 1;
+}
+
+static int cmp_etseq(m_etseq *b1, m_etseq *b2)
+{
+ int i;
+
+ if (b1->_length != b2->_length)
+ return 0;
+ for (i = 0; i < b1->_length; i++)
+ if (!erl_match(b1->_buffer[i], b2->_buffer[i]))
+ return 0;
+ return 1;
+}
+
+static int cmp_et(m_et* b1, m_et *b2)
+{
+ return erl_match(b1->e, b2->e) && b1->l == b2->l;
+}
+
+static int cmp_es(m_es *b1, m_es *b2)
+{
+ return b1->f == b2->f && b1->l == b2->l;
+}
+
+static int cmp_arr1(m_arr1 b1, m_arr1 b2)
+{
+ int i;
+
+ for (i = 0; i < 500; i++)
+ if (b1[i] != b2[i])
+ return 0;
+ return 1;
+}
+
+static int cmp_dd(m_dd b1, m_dd b2)
+{
+
+ int i, j;
+
+ for (i = 0; i < 2; i++)
+ for (j = 0; j < 3; j++)
+ if (b1[i][j] != b2[i][j])
+ return 0;
+ return 1;
+}
+
+
+
+static int cmp_strRec(m_strRec *b1, m_strRec *b2)
+{
+ int i, j;
+
+ if (b1->bb != b2->bb)
+ return 0;
+ if (!cmp_str(b1->str4,b2->str4))
+ return 0;
+ if (b1->str5._length != b2->str5._length)
+ return 0;
+ for (j = 0; j < b1->str5._length; j++)
+ if (b1->str5._buffer[j] != b2->str5._buffer[j])
+ return 0;
+ if (!cmp_str(b1->str6,b2->str6))
+ return 0;
+ for (i = 0; i < 2; i++)
+ for (j = 0; j < 3; j++)
+ if (b1->str7[i][j] != b2->str7[i][j])
+ return 0;
+ for (j = 0; j < 3; j++)
+ if (b1->str8[j] != b2->str8[j])
+ return 0;
+ if (!cmp_str(b1->str9,b2->str9))
+ return 0;
+ if (b1->str10._length != b2->str10._length)
+ return 0;
+ for (j = 0; j < b1->str10._length; j++)
+ if (b1->str10._buffer[j] != b2->str10._buffer[j])
+ return 0;
+ return 1;
+}
+
+
+static int cmp_sseq(m_sseq *b1, m_sseq *b2)
+{
+ int i;
+
+ if (b1->_length != b2->_length)
+ return 0;
+ for (i = 0; i < b1->_length; i++)
+ if (!cmp_str(b1->_buffer[i], b2->_buffer[i]))
+ return 0;
+ return 1;
+}
+
+
+static int cmp_pid(erlang_pid *p1, erlang_pid *p2)
+{
+ return cmp_str(p1->node,p2-> node) &&
+ p1->num == p2->num &&
+ p1->serial == p2->serial &&
+ p1->creation == p2->creation;
+}
+
+static int cmp_port(erlang_port *p1, erlang_port *p2)
+{
+ return cmp_str(p1->node,p2-> node) && p1->id == p2->id;
+}
+
+static int cmp_ref(erlang_ref *p1, erlang_ref *p2)
+{
+ return cmp_str(p1->node, p2->node) &&
+ p1->len == p2->len &&
+ (p1->len < 1 || p1->n[0] == p2->n[0]) &&
+ (p1->len < 2 || p1->n[1] == p2->n[1]) &&
+ (p1->len < 3 || p1->n[2] == p2->n[2]);
+}
+
+static int cmp_s(m_s *b1, m_s *b2)
+{
+ int i;
+
+ if (b1->l != b2->l)
+ return 0;
+ if (b1->sl._length != b2->sl._length)
+ return 0;
+ for (i = 0; i < b1->sl._length; i++)
+ if (b1->sl._buffer[i] != b2->sl._buffer[i])
+ return 0;
+ return 1;
+}
+
+
+static int cmp_ssstr3(m_ssstr3 *b1, m_ssstr3 *b2)
+{
+ int i,j;
+
+ if (b1->_length != b2->_length)
+ return 0;
+ for (i = 0; i < b1->_length; i++) {
+ if (b1->_buffer[i]._length != b2->_buffer[i]._length)
+ return 0;
+ for (j = 0; j < b1->_buffer[i]._length; j++)
+ if (!cmp_str(b1->_buffer[i]._buffer[j],
+ b2->_buffer[i]._buffer[j]))
+ return 0;
+ }
+ return 1;
+}
+
+
+
+static int cmp_ssarr3(m_ssarr3 *b1, m_ssarr3 *b2)
+{
+ int i;
+
+ if (b1->_length != b2->_length)
+ return 0;
+ for (i = 0; i < b1->_length; i++) {
+ if (!cmp_sarr3(&b1->_buffer[i], &b2->_buffer[i]))
+ return 0;
+ }
+ return 1;
+}
+
+static int cmp_sarr3(m_sarr3 *b1, m_sarr3 *b2)
+{
+ int i;
+
+ if (b1->_length != b2->_length)
+ return 0;
+ for (i = 0; i < b1->_length; i++) {
+ if (!cmp_arr3(b1->_buffer[i], b2->_buffer[i]))
+ return 0;
+ }
+ return 1;
+}
+
+static int cmp_arr3(m_arr3 b1, m_arr3 b2)
+{
+ int i;
+
+ for (i = 0; i < sizeof(m_arr3)/sizeof(CORBA_long); i++) {
+ if (b1[i] != b2[i])
+ return 0;
+ }
+ return 1;
+}
+
+/* Print functions */
+static void print_aseq(m_aseq *a)
+{
+ int i;
+ fprintf(stdout, "\nm_aseq size: %ld --------\n", a->_length);
+ for (i = 0; i < a->_length; i++)
+ print_a(&(a->_buffer[i]));
+}
+
+static void print_a(m_a *a)
+{
+ fprintf(stdout, "\nm_a --------\n l: %ld\n d:%f\n", a->l, a->d);
+ print_bseq(&a->y);
+}
+
+static void print_bseq(m_bseq *b)
+{
+ int i;
+
+ fprintf(stdout, "\nm_bseq size: %ld --------\n",b->_length);
+ for (i = 0; i < b->_length; i++)
+ print_b(&(b->_buffer[i]));
+}
+
+static void print_lseq(m_lseq *b)
+{
+ int i;
+
+ fprintf(stdout, "\nm_lseq size: %ld --------\n",b->_length);
+ for (i = 0; i < b->_length; i++)
+ fprintf(stdout, "[%d]: %ld\n", i, b->_buffer[i]);
+}
+
+static void print_b(m_b *b)
+{
+ fprintf(stdout, "\nm_b --------\n l: %ld\n c: %c\n", b->l, b->c);
+}
+
+
+static void print_etseq(m_etseq *b)
+{
+ int i;
+
+ for (i = 0; i < b->_length; i++) {
+ fprintf(stdout, "[%d]:\n", i);
+ erl_print_term(stdout, b->_buffer[i]);
+ }
+}
+
+
+static void print_et(m_et* b)
+{
+ fprintf(stdout, "\net struct --------\n");
+ erl_print_term(stdout, b->e);
+ fprintf(stdout, "long: %ld\n", b->l);
+ fprintf(stdout, "\n--------\n");
+}
+
+static void print_es(m_es *b)
+{
+ fprintf(stdout, "\nm_es --------\n f: %d\n l: %ld\n", b->f, b->l);
+}
+
+
+static void print_arr1(long a[10])
+{
+ int i;
+
+ for (i = 0; i < 10; i++)
+ fprintf(stdout, "\n[%d]: %ld\n", i, a[i]);
+}
+
+static void print_dd(long a[2][3])
+{
+ int i, j;
+
+ fprintf(stdout, "\nlong dd[2][3] --------\n");
+ for (i = 0; i < 2; i++)
+ for (j = 0; j < 3; j++)
+ fprintf(stdout, "\n[%d][%d]: %ld\n", i, j, a[i][j]);
+}
+
+
+static void print_strRec(m_strRec* sr)
+{
+ int i, j;
+
+ fprintf(stdout, "\nboolean bb : %d\n",sr->bb);
+ fprintf(stdout, "string str4 : %s\n",sr->str4);
+ fprintf(stdout, "str7[2][3] :\n");
+ for (i = 0; i < 2; i++)
+ for (j = 0; j < 3; j++)
+ fprintf(stdout, "str7[%d][%d]: %ld\n", i, j, sr->str7[i][j]);
+ fprintf(stdout, "str5._length : %ld\n",sr->str5._length);
+ for (j = 0; j < sr->str5._length; j++)
+ fprintf(stdout, "str5._buffer[%d]: %c\n", j, sr->str5._buffer[j]);
+ fprintf(stdout, "string str6 : %s\n",sr->str6);
+ fprintf(stdout, "str8 :\n");
+ for (j = 0; j < 3; j++)
+ fprintf(stdout, "str8[%d]: %c\n", j, sr->str8[j]);
+ fprintf(stdout, "string str9 : %s\n",sr->str9);
+ fprintf(stdout, "str10._length : %ld\n",sr->str10._length);
+ for (j = 0; j < sr->str10._length; j++)
+ fprintf(stdout, "str10._buffer[%d]: %c\n", j, sr->str10._buffer[j]);
+}
+
+static void print_sseq(m_sseq *b)
+{
+ int i;
+
+ fprintf(stdout, "\nm_sseq size: %ld --------\n",b->_length);
+ for (i = 0; i < b->_length; i++)
+ fprintf(stdout, "%s\n", b->_buffer[i]);
+
+}
+
+
+static void print_pid(erlang_pid *p)
+{
+ fprintf(stdout, "\nerlang_pid --------\n node: %s\n num: %d\n "
+ "serial: %d\n creation: %d\n",
+ p->node, p->num, p->serial, p->creation);
+}
+
+static void print_port(erlang_port *p)
+{
+ fprintf(stdout, "\nerlang_port --------\n node: %s\n id: %d\n "
+ "creation: %d\n", p->node, p->id, p->creation);
+}
+
+static void print_ref(erlang_ref *p)
+{
+ fprintf(stdout, "\nerlang_ref --------\n node: %s\n len: %d\n "
+ "n[0]: %d\n n[1]: %d\n n[2]: %d\n creation: %d\n",
+ p->node, p->len, p->n[0], p->n[1], p->n[2], p->creation);
+}
+
+static void print_term(ETERM *t)
+{
+ fprintf(stdout, "\nETERM --------\n");
+ erl_print_term(stdout, t);
+ fprintf(stdout, "\n--------\n");
+}
+
+static void print_s(m_s *p)
+{
+ int i;
+
+ fprintf(stdout, "\n%ld\n", p->l);
+ for (i = 0; i < p->sl._length; i++)
+ fprintf(stdout, "\n[%d]: %ld\n", i, p->sl._buffer[i]);
+}
+
+
+static void print_ssstr3(m_ssstr3 *b1)
+{
+ int i,j;
+
+ fprintf(stdout, "\nSSSTR3 --------\n");
+ fprintf(stdout,"b1->_length = %ld\n",b1->_length);
+ for (i = 0; i < b1->_length; i++) {
+ fprintf(stdout,"\nb1->_buffer[%d]._length %ld\n",
+ i, b1->_buffer[i]._length);
+ for (j = 0; j < b1->_buffer[i]._length; j++)
+ fprintf(stdout,"b1->_buffer[%d]._buffer[%d] = %s\n",
+ i, j, b1->_buffer[i]._buffer[j]);
+ }
+ fprintf(stdout, "\n--------\n");
+}
+
+static void print_wstr(CORBA_wchar *ws)
+{
+ int i = 0;
+
+ fprintf(stdout, "\nwstr --------\n");
+ while (ws[i]) {
+ fprintf(stdout, "[%d]: %ld\n", i, ws[i]);
+ i++;
+ }
+ fprintf(stdout, "\n--------\n");
+}
+
+
+static void print_ssarr3(m_ssarr3 *b1)
+{
+ int i;
+
+ fprintf(stdout, "\nssarr3 --------\n");
+ fprintf(stdout,"length: %ld\n",b1->_length);
+ fprintf(stdout, "buffer:\n");
+ for (i = 0; i < b1->_length; i++)
+ print_sarr3(&b1->_buffer[i]);
+ fprintf(stdout, "\n--------\n");
+}
+
+static void print_sarr3(m_sarr3 *b1)
+{
+ int i;
+
+ fprintf(stdout, "\nsarr3 --------\n");
+ fprintf(stdout,"length: %ld\n",b1->_length);
+ fprintf(stdout, "buffer:\n");
+ for (i = 0; i < b1->_length; i++)
+ print_arr3(b1->_buffer[i]);
+ fprintf(stdout, "\n--------\n");
+}
+
+static void print_arr3(m_arr3 b1)
+{
+ int i;
+
+ fprintf(stdout, "\narr3 --------\n");
+ for (i = 0; i < sizeof(m_arr3)/sizeof(CORBA_long); i++)
+ fprintf(stdout, "%ld ", b1[i]);
+ fprintf(stdout, "\n--------\n");
+}
+
+static void free_etseq_buf(m_etseq *b)
+{
+ int i;
+
+ for (i = 0; i < b->_length; i++)
+ erl_free_term(b->_buffer[i]);
+}
+
+static void free_et(m_et* b)
+{
+ erl_free_term(b->e);
+}
+
+static void showtime(MyTimeval *start, MyTimeval *stop)
+{
+ MyTimeval elapsed;
+
+ elapsed.tv_sec = stop->tv_sec - start->tv_sec;
+ elapsed.tv_usec = stop->tv_usec - start->tv_usec;
+ while (elapsed.tv_usec < 0) {
+ elapsed.tv_sec -= 1;
+ elapsed.tv_usec += 1000000;
+ }
+ fprintf(stderr,"%ld.%06ld seconds\n",elapsed.tv_sec, elapsed.tv_usec);
+}
+
+static void my_gettimeofday(MyTimeval *tv)
+#ifdef __WIN32__
+#define EPOCH_JULIAN_DIFF 11644473600i64
+{
+ SYSTEMTIME t;
+ FILETIME ft;
+ LONGLONG lft;
+
+ GetSystemTime(&t);
+ SystemTimeToFileTime(&t, &ft);
+ memcpy(&lft, &ft, sizeof(lft));
+ tv->tv_usec = (long) ((lft / 10i64) % 1000000i64);
+ tv->tv_sec = (long) ((lft / 10000000i64) - EPOCH_JULIAN_DIFF);
+}
+#elif defined VXWORKS
+{
+ int rate = sysClkRateGet(); /* Ticks per second */
+ unsigned long ctick = tickGet();
+ tv->tv_sec = ctick / rate; /* secs since reboot */
+ tv->tv_usec = ((ctick - (tv->tv_sec * rate))*1000000)/rate;
+}
+#else
+{
+ gettimeofday(tv, NULL);
+}
+#endif
diff --git a/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/c_erl_test.idl b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/c_erl_test.idl
new file mode 100644
index 0000000000..e687cec114
--- /dev/null
+++ b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/c_erl_test.idl
@@ -0,0 +1,173 @@
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 2004-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+#include "erlang.idl"
+
+
+const short TestConst = 1;
+
+module m {
+
+ const short TestConst = 2;
+
+ struct b {
+ long l;
+ char c;
+ };
+
+ struct simple {
+ long l;
+ b b_t;
+ };
+
+ enum fruit {orange, banana, apple, peach, pear};
+
+ typedef sequence<long> lseq;
+
+ typedef sequence<b> bseq;
+
+ struct a {
+ long l;
+ bseq y;
+ double d;
+ };
+
+ typedef sequence<a> aseq;
+
+ typedef sequence<string> sseq;
+ typedef string str;
+ typedef long myLong;
+
+ typedef long arr1[500], dd[2][3];
+
+ typedef erlang::term apa;
+ typedef erlang::port banan;
+
+ typedef sequence<erlang::term> etseq;
+
+ struct s {
+ long l;
+ sequence<long> sl;
+ };
+
+ struct es {
+ fruit f;
+ myLong l;
+ };
+
+ struct et {
+ erlang::term e;
+ long l;
+ };
+
+
+ typedef sequence<char> str1;
+ typedef string<12> str2;
+ typedef char str3[3];
+
+ typedef sequence<string> sstr3; // sequence of string
+ typedef sequence<sstr3> ssstr3; // sequence of sequences of strings
+
+ typedef long arr3[3]; // array of long
+ typedef sequence<arr3> sarr3; // sequence of array
+ typedef sequence<sarr3> ssarr3; // sequence of sequnces of arrays of strings
+
+ struct strRec{
+ boolean bb;
+ string str4;
+ long str7[3][2];
+ sequence<char> str5;
+ string<12> str6;
+ str3 str8;
+ str2 str9;
+ str1 str10;
+ };
+
+
+ struct dyn {
+ long l;
+ sequence<long> sl;
+ };
+ typedef dyn arr2[1][2];
+
+
+ interface i {
+
+ const short TestConst = 3;
+
+ //arr2 suck(in arr2 x, out arr2 y );
+
+ ///////////////////////////////// attribute long l;
+
+ // simple types
+ void void_test();
+ long long_test(in long a, out long a1);
+ long long longlong_test(in long long a, out long long a1);
+ unsigned short ushort_test(in unsigned short a, out unsigned short a1);
+ unsigned long ulong_test(in unsigned long a, out unsigned long a1);
+ unsigned long long ulonglong_test(in unsigned long long a, out unsigned long long a1);
+ double double_test(in double a, out double a1);
+ char char_test(in char a, out char a1);
+ wchar wchar_test(in wchar a, out wchar a1);
+ octet octet_test(in octet a, out octet a1);
+ boolean bool_test(in boolean a, out boolean a1);
+
+ // Seq. and struct tests
+ b struct_test(in b a, out b a1);
+ es struct2_test(in es a, out es a1);
+ //simple struct3_test(in simple x, out simple y);
+ bseq seq1_test(in bseq a, out bseq a1);
+ aseq seq2_test(in aseq a, out aseq a1);
+ lseq seq3_test(in lseq a, out lseq a1);
+ ssstr3 seq4_test(in ssstr3 a, out ssstr3 a1);
+ ssarr3 seq5_test(in ssarr3 a, out ssarr3 a1);
+
+ // Array tests
+ arr1 array1_test(in arr1 a, out arr1 a1);
+ dd array2_test(in dd a, out dd a1);
+
+ // enum test
+ fruit enum_test(in fruit a, out fruit a1);
+
+ // string tests
+ string string1_test(in string a, out string a1);
+ wstring wstring1_test(in wstring a, out wstring a1);
+ sseq string2_test(in sseq a, out sseq a1);
+ str string3_test(in str a, out str a1);
+ strRec string4_test(in strRec a, out strRec a1);
+
+ // Special erlang types
+ erlang::pid pid_test(in erlang::pid a, out erlang::pid a1);
+ erlang::port port_test(in erlang::port a, out erlang::port a1);
+ erlang::ref ref_test(in erlang::ref a, out erlang::ref a1);
+ erlang::term term_test(in erlang::term a, out erlang::term a1);
+
+ // typedef test
+ long typedef_test(in apa a, in banan b, out apa a1, out banan b1);
+
+ // inlined seq. test
+ s inline_sequence_test(in s a, out s a1);
+
+ // term seq. test
+ etseq term_sequence_test(in etseq a, out etseq a1);
+ // term struct test
+ et term_struct_test(in et a, out et a1);
+
+ };
+
+};
diff --git a/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/erl_server.erl b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/erl_server.erl
new file mode 100644
index 0000000000..2e624ec5c0
--- /dev/null
+++ b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/erl_server.erl
@@ -0,0 +1,28 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+-module(erl_server).
+
+-export([run/0, stop/0]).
+
+run() ->
+ m_i:oe_create().
+
+stop() ->
+ gen_server:cast(cidl_test, stop).
diff --git a/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/m_i_impl.erl b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/m_i_impl.erl
new file mode 100644
index 0000000000..0c96fb9edf
--- /dev/null
+++ b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/m_i_impl.erl
@@ -0,0 +1,161 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+-module(m_i_impl).
+-include("m.hrl").
+
+-export([init/1, terminate/2, void_test/1, long_test/2, ushort_test/2,
+ longlong_test/2, ulong_test/2, ulonglong_test/2,
+ double_test/2, char_test/2, wchar_test/2, octet_test/2,
+ bool_test/2, struct_test/2, struct2_test/2, seq1_test/2,
+ seq2_test/2, seq3_test/2, seq4_test/2, seq5_test/2,
+ array1_test/2, array2_test/2, enum_test/2, string1_test/2,
+ string2_test/2, string3_test/2, string4_test/2, pid_test/2,
+ port_test/2, ref_test/2, term_test/2, typedef_test/3,
+ inline_sequence_test/2, '_set_l'/2, '_get_l'/1,
+ term_struct_test/2, term_sequence_test/2, wstring1_test/2]).
+
+-define(PRINTDEBUG(Case),
+ io:format("erl_server: case: ~p~n"
+ "erl_server: location: ~p~n", [Case, [?FILE, ?LINE]])).
+-define(PRINTDEBUG2(Case, Msg),
+ io:format("erl_server: case: ~p~n"
+ "erl_server: Msg: ~p~n"
+ "erl_server: location: ~p~n", [Case, Msg, [?FILE, ?LINE]])).
+
+init(Env) ->
+ {ok, []}.
+
+terminate(F, R) ->
+ ok.
+
+'_get_l'(State) ->
+ ?PRINTDEBUG("_get_l"),
+ {reply, State, State}.
+void_test(State) ->
+ ?PRINTDEBUG("void_test"),
+ {reply, ok, State}.
+
+'_set_l'(State, V) ->
+ ?PRINTDEBUG2("_set_l", V),
+ {reply, ok, V}.
+ushort_test(State, V) ->
+ ?PRINTDEBUG2("ushort_test", V),
+ {reply, {V, V}, State}.
+long_test(State, V) ->
+ ?PRINTDEBUG2("long_test", V),
+ {reply, {V, V}, State}.
+longlong_test(State, V) ->
+ ?PRINTDEBUG2("longlong_test", V),
+ {reply, {V, V}, State}.
+ulong_test(State, V) ->
+ ?PRINTDEBUG2("ulong_test", V),
+ {reply, {V, V}, State}.
+ulonglong_test(State, V) ->
+ ?PRINTDEBUG2("ulonglong_test", V),
+ {reply, {V, V}, State}.
+double_test(State, V) ->
+ ?PRINTDEBUG2("double_test", V),
+ {reply, {V, V}, State}.
+char_test(State, V) ->
+ ?PRINTDEBUG2("char_test", V),
+ {reply, {V, V}, State}.
+wchar_test(State, V) ->
+ ?PRINTDEBUG2("wchar_test", V),
+ {reply, {V, V}, State}.
+octet_test(State, V) ->
+ ?PRINTDEBUG2("octet_test", V),
+ {reply, {V, V}, State}.
+bool_test(State, V) ->
+ ?PRINTDEBUG2("bool_test", V),
+ {reply, {V, V}, State}.
+
+struct_test(State, V) ->
+ ?PRINTDEBUG2("struct_test", V),
+ {reply, {V, V}, State}.
+struct2_test(State, V) ->
+ ?PRINTDEBUG2("struct2_test", V),
+ {reply, {V, V}, State}.
+seq1_test(State, V) ->
+ ?PRINTDEBUG2("seq1_test", V),
+ {reply, {V, V}, State}.
+seq2_test(State, V) ->
+ ?PRINTDEBUG2("seq2_test", V),
+ {reply, {V, V}, State}.
+seq3_test(State, V) ->
+ ?PRINTDEBUG2("seq3_test", V),
+ {reply, {V, V}, State}.
+seq4_test(State, V) ->
+ ?PRINTDEBUG2("seq4_test", V),
+ {reply, {V, V}, State}.
+seq5_test(State, V) ->
+ ?PRINTDEBUG2("seq5_test", V),
+ {reply, {V, V}, State}.
+array1_test(State, V) ->
+ ?PRINTDEBUG2("array1_test", V),
+ {reply, {V, V}, State}.
+array2_test(State, V) ->
+ ?PRINTDEBUG2("array2_test", V),
+ {reply, {V, V}, State}.
+enum_test(State, V) ->
+ ?PRINTDEBUG2("enum_test", V),
+ {reply, {V, V}, State}.
+string1_test(State, V) ->
+ ?PRINTDEBUG2("string1_test", V),
+ {reply, {V, V}, State}.
+string2_test(State, V) ->
+ ?PRINTDEBUG2("string2_test", V),
+ {reply, {V, V}, State}.
+string3_test(State, V) ->
+ ?PRINTDEBUG2("string3_test", V),
+ {reply, {V, V}, State}.
+string4_test(State, V) ->
+ ?PRINTDEBUG2("string4_test", V),
+ {reply, {V, V}, State}.
+pid_test(State, V) ->
+ ?PRINTDEBUG2("pid_test", V),
+ {reply, {V, V}, State}.
+port_test(State, V) ->
+ ?PRINTDEBUG2("port_test", binary_to_list(term_to_binary(V))),
+ {reply, {V, V}, State}.
+ref_test(State, V) ->
+ ?PRINTDEBUG2("ref_test", binary_to_list(term_to_binary(V))),
+ {reply, {V, V}, State}.
+term_test(State, V) ->
+ ?PRINTDEBUG2("term_test", V),
+ {reply, {V, V}, State}.
+typedef_test(State, A, B) ->
+ ?PRINTDEBUG2("typedef_test", [A,B]),
+ {reply, {4711, A, B}, State}.
+inline_sequence_test(State, V) ->
+ ?PRINTDEBUG2("inline_sequence_test", V),
+ {reply, {V, V}, State}.
+term_sequence_test(State, V) ->
+ ?PRINTDEBUG2("term_sequence_test", V),
+ {reply, {V, V}, State}.
+term_struct_test(State, V) ->
+ ?PRINTDEBUG2("term_struct_test", V),
+ {reply, {V, V}, State}.
+wstring1_test(State, V) ->
+ ?PRINTDEBUG2("wstring1_test", V),
+ {reply, {V, V}, State}.
+
+
+
+
diff --git a/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/my.c b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/my.c
new file mode 100644
index 0000000000..4e0be3fec1
--- /dev/null
+++ b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/my.c
@@ -0,0 +1,51 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2004-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+ */
+#include "ic.h"
+#include "m_i.h"
+
+int my_prepare_notification_encoding(CORBA_Environment *env)
+{
+ return oe_prepare_notification_encoding(env);
+}
+
+int my_send_notification_tmo(CORBA_Environment *env, unsigned int send_ms)
+{
+ return oe_send_notification_tmo(env, send_ms);
+}
+
+int my_prepare_request_encoding(CORBA_Environment *env)
+{
+ return oe_prepare_request_encoding(env);
+}
+
+int my_send_request_and_receive_reply_tmo(CORBA_Environment *env,
+ unsigned int send_ms,
+ unsigned int recv_ms)
+{
+ return oe_send_request_and_receive_reply_tmo(env, send_ms, recv_ms);
+}
+
+int my_prepare_reply_decoding(CORBA_Environment *env)
+{
+ return oe_prepare_reply_decoding(env);
+}
+
+
+
diff --git a/lib/ic/test/erl_client_c_server_SUITE.erl b/lib/ic/test/erl_client_c_server_SUITE.erl
new file mode 100644
index 0000000000..c5f5b6a218
--- /dev/null
+++ b/lib/ic/test/erl_client_c_server_SUITE.erl
@@ -0,0 +1,350 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+
+%%----------------------------------------------------------------------
+%% Purpose : Test suite for erl-client/c-server
+%%----------------------------------------------------------------------
+
+
+-module(erl_client_c_server_SUITE).
+-include("test_server.hrl").
+
+-export([init_per_testcase/2, fin_per_testcase/2, all/1, void_test/1,
+ long_test/1, longlong_test/1, ushort_test/1, ulong_test/1,
+ ulonglong_test/1, double_test/1, char_test/1, wchar_test/1,
+ octet_test/1, bool_test/1, struct_test/1, struct2_test/1,
+ seq1_test/1, seq2_test/1, seq3_test/1, seq4_test/1,
+ seq5_test/1, array1_test/1, array2_test/1, enum_test/1,
+ string1_test/1, string2_test/1, string3_test/1,
+ string4_test/1, pid_test/1, port_test/1, ref_test/1,
+ term_test/1, typedef_test/1, inline_sequence_test/1,
+ term_sequence_test/1, term_struct_test/1, wstring1_test/1]).
+
+-define(DEFAULT_TIMEOUT, 20000).
+-define(PORT_TIMEOUT, 15000).
+-define(CALL_TIMEOUT, 5000).
+
+-define(C_SERVER_NODE_NAME, idl_c_server_test).
+
+%% Add/remove code path and watchdog before/after each test case.
+%%
+init_per_testcase(_Case, Config) ->
+ DataDir = ?config(data_dir, Config),
+ code:add_patha(DataDir),
+
+ %% Since other test suites use the module m_i, we have
+ %% to make sure we are using the right m_i module.
+ code:purge(m_i),
+ code:load_file(m_i),
+
+ WatchDog = test_server:timetrap(?DEFAULT_TIMEOUT),
+ [{watchdog, WatchDog}| Config].
+
+fin_per_testcase(_Case, Config) ->
+ DataDir = ?config(data_dir, Config),
+ code:del_path(DataDir),
+ WatchDog = ?config(watchdog, Config),
+ test_server:timetrap_cancel(WatchDog).
+
+all(doc) ->
+ "Test of IC with an Erlang client and a C server. "
+ "The communication is via Erlang distribution.";
+all(suite) ->
+ [void_test, long_test, longlong_test, ushort_test,
+ ulong_test, ulonglong_test, double_test,
+ char_test, wchar_test, octet_test, bool_test, struct_test,
+ struct2_test, seq1_test, seq2_test, seq3_test, seq4_test,
+ seq5_test, array1_test, array2_test, enum_test, string1_test,
+ string2_test, string3_test, string4_test, pid_test, port_test,
+ ref_test, term_test, typedef_test, inline_sequence_test,
+ term_sequence_test, term_struct_test, wstring1_test].
+
+
+array1_test(doc) -> "";
+array1_test(suite) -> [];
+array1_test(Config) ->
+ do_test(array1_test, Config).
+
+array2_test(doc) -> "";
+array2_test(suite) -> [];
+array2_test(Config) ->
+ do_test(array2_test, Config).
+
+bool_test(doc) -> "";
+bool_test(suite) -> [];
+bool_test(Config) ->
+ do_test(bool_test, Config).
+
+char_test(doc) -> "";
+char_test(suite) -> [];
+char_test(Config) ->
+ do_test(char_test, Config).
+
+double_test(doc) -> "";
+double_test(suite) -> [];
+double_test(Config) ->
+ do_test(double_test, Config).
+
+enum_test(doc) -> "";
+enum_test(suite) -> [];
+enum_test(Config) ->
+ do_test(enum_test, Config).
+
+inline_sequence_test(doc) -> "";
+inline_sequence_test(suite) -> [];
+inline_sequence_test(Config) ->
+ do_test(inline_sequence_test, Config).
+
+longlong_test(doc) -> "";
+longlong_test(suite) -> [];
+longlong_test(Config) ->
+ do_test(longlong_test, Config).
+
+long_test(doc) -> "";
+long_test(suite) -> [];
+long_test(Config) ->
+ do_test(long_test, Config).
+
+octet_test(doc) -> "";
+octet_test(suite) -> [];
+octet_test(Config) ->
+ do_test(octet_test, Config).
+
+pid_test(doc) -> "";
+pid_test(suite) -> [];
+pid_test(Config) ->
+ do_test(pid_test, Config).
+
+port_test(doc) -> "";
+port_test(suite) -> [];
+port_test(Config) ->
+ do_test(port_test, Config).
+
+ref_test(doc) -> "";
+ref_test(suite) -> [];
+ref_test(Config) ->
+ do_test(ref_test, Config).
+
+seq1_test(doc) -> "";
+seq1_test(suite) -> [];
+seq1_test(Config) ->
+ do_test(seq1_test, Config).
+
+seq2_test(doc) -> "";
+seq2_test(suite) -> [];
+seq2_test(Config) ->
+ do_test(seq2_test, Config).
+
+seq3_test(doc) -> "";
+seq3_test(suite) -> [];
+seq3_test(Config) ->
+ do_test(seq3_test, Config).
+
+seq4_test(doc) -> "";
+seq4_test(suite) -> [];
+seq4_test(Config) ->
+ do_test(seq4_test, Config).
+
+seq5_test(doc) -> "";
+seq5_test(suite) -> [];
+seq5_test(Config) ->
+ do_test(seq5_test, Config).
+
+string1_test(doc) -> "";
+string1_test(suite) -> [];
+string1_test(Config) ->
+ do_test(string1_test, Config).
+
+string2_test(doc) -> "";
+string2_test(suite) -> [];
+string2_test(Config) ->
+ do_test(string2_test, Config).
+
+string3_test(doc) -> "";
+string3_test(suite) -> [];
+string3_test(Config) ->
+ do_test(string3_test, Config).
+
+string4_test(doc) -> "";
+string4_test(suite) -> [];
+string4_test(Config) ->
+ do_test(string4_test, Config).
+
+struct2_test(doc) -> "";
+struct2_test(suite) -> [];
+struct2_test(Config) ->
+ do_test(struct2_test, Config).
+
+struct_test(doc) -> "";
+struct_test(suite) -> [];
+struct_test(Config) ->
+ do_test(struct_test, Config).
+
+term_sequence_test(doc) -> "";
+term_sequence_test(suite) -> [];
+term_sequence_test(Config) ->
+ do_test(term_sequence_test, Config).
+
+term_struct_test(doc) -> "";
+term_struct_test(suite) -> [];
+term_struct_test(Config) ->
+ do_test(term_struct_test, Config).
+
+term_test(doc) -> "";
+term_test(suite) -> [];
+term_test(Config) ->
+ do_test(term_test, Config).
+
+typedef_test(doc) -> "";
+typedef_test(suite) -> [];
+typedef_test(Config) ->
+ do_test(typedef_test, Config).
+
+ulonglong_test(doc) -> "";
+ulonglong_test(suite) -> [];
+ulonglong_test(Config) ->
+ do_test(ulonglong_test, Config).
+
+ulong_test(doc) -> "";
+ulong_test(suite) -> [];
+ulong_test(Config) ->
+ do_test(ulong_test, Config).
+
+ushort_test(doc) -> "";
+ushort_test(suite) -> [];
+ushort_test(Config) ->
+ do_test(ushort_test, Config).
+
+void_test(doc) -> "";
+void_test(suite) -> [];
+void_test(Config) ->
+ do_test(void_test, Config).
+
+wchar_test(doc) -> "";
+wchar_test(suite) -> [];
+wchar_test(Config) ->
+ do_test(wchar_test, Config).
+
+wstring1_test(doc) -> "";
+wstring1_test(suite) -> [];
+wstring1_test(Config) ->
+ do_test(wstring1_test, Config).
+
+
+do_test(Case, Config) ->
+ %% Trap exits
+ process_flag(trap_exit, true),
+ Node = atom_to_list(node()),
+ [_NodeName, HostName] = string:tokens(Node, "@"),
+ DataDir = ?config(data_dir, Config),
+ %% io:format("~p: data directory: ~p~n", [?MODULE, DataDir]),
+ Cookie = atom_to_list(erlang:get_cookie()),
+ ServerNodeName = atom_to_list(?C_SERVER_NODE_NAME),
+ %% Start C-server node as a port program. We wait for the node
+ %% to connect to us.
+ Cmd = filename:join([DataDir, "c_server"]) ++
+ " -this-node-name " ++ ServerNodeName ++
+ " -peer-node " ++ Node ++
+ " -cookie " ++ Cookie,
+ Port = open_port({spawn, Cmd}, [exit_status, eof, stderr_to_stdout]),
+ ServerNode = list_to_atom(ServerNodeName ++ "@" ++ HostName),
+ Res = case wait_for_hidden_node(ServerNode) of
+ ok ->
+ %% Need a port for port_test and typedef_test
+ put(port_test_port, Port),
+ R = (catch erl_client:Case(ServerNode, ?CALL_TIMEOUT)),
+ case wait_for_completion(Port) of
+ {error, timeout} ->
+ kill_off_node(ServerNode);
+ _ ->
+ ok
+ end,
+ R;
+ {error, timeout} ->
+ case wait_for_completion(Port) of
+ {error, timeout} ->
+ kill_off_node(ServerNode);
+ _ ->
+ ok
+ end,
+ {error, timeout}
+ end,
+ process_flag(trap_exit, false),
+ true = Res.
+
+
+%% Wait for eof *and* exit status, but return if exit status indicates
+%% an error, or we have been waiting more than PORT_TIMEOUT seconds.
+%%
+wait_for_completion(Port) ->
+ wait_for_completion(Port, 0).
+
+wait_for_completion(Port, N) when N < 2 ->
+ receive
+ {Port, {data, Bytes}} ->
+ %% Relay output
+ io:format("~s", [Bytes]),
+ wait_for_completion(Port, N);
+ {Port, {exit_status, 0}} ->
+ wait_for_completion(Port, N + 1);
+ {Port, {exit_status, Status}} ->
+ {error, Status};
+ {Port, eof} ->
+ wait_for_completion(Port, N + 1);
+ {'EXIT', Port, Reason} ->
+ io:format("Port exited with reason: ~w~n", [Reason]),
+ wait_for_completion(Port, N);
+ {'EXIT', From, Reason} ->
+ io:format("Got unexpected exit: ~p~n", [{'EXIT', From, Reason}]),
+ wait_for_completion(Port, N)
+ after ?PORT_TIMEOUT ->
+ {error, timeout}
+ end;
+wait_for_completion(_, _) ->
+ ok.
+
+wait_for_hidden_node(Node) ->
+ Times = ?DEFAULT_TIMEOUT div 100,
+ wait_for_hidden_node(Node, Times, 100).
+
+wait_for_hidden_node(Node, Times, WaitTime) when Times > 0 ->
+ io:format("Waiting for hidden node: ~p~n", [Node]),
+ case lists:member(Node, erlang:nodes(hidden)) of
+ true ->
+ ok;
+ false ->
+ delay(WaitTime),
+ wait_for_hidden_node(Node, Times - 1, WaitTime)
+ end;
+wait_for_hidden_node(_Node, _, _WaitTime) ->
+ {error, timeout}.
+
+kill_off_node(Node) ->
+ catch rpc:cast(Node, erlang, halt, [1]).
+
+delay(Time) ->
+ receive
+ after Time ->
+ ok
+ end.
+
+
+
+
diff --git a/lib/ic/test/erl_client_c_server_SUITE_data/Makefile.src b/lib/ic/test/erl_client_c_server_SUITE_data/Makefile.src
new file mode 100644
index 0000000000..cd34d2b247
--- /dev/null
+++ b/lib/ic/test/erl_client_c_server_SUITE_data/Makefile.src
@@ -0,0 +1,150 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2002-2009. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+#
+# Makefile.src for erl_client_c_server test
+# Note: This file *must* work for both Unix and Windows
+#
+# We use both `rm' (Unix) and `del' (Windows) for removing files, but
+# with a `-' in front so that the error in not finding `rm' (`del') on
+# Windows (Unix) is ignored.
+#
+# VxWorks? XXX
+#
+
+.SUFFIXES:
+.SUFFIXES: .c .h .erl .idl @obj@ .@EMULATOR@
+
+
+# Variables from ts:
+#
+
+ERL_INCLUDE = @erl_include@
+
+IC_INCLUDE_PATH = @ic_include_path@
+IC_LIB = @ic_libpath@@DS@@ic_lib@
+
+ERL_INTERFACE_INCLUDE = @erl_interface_include@
+ERL_INTERFACE_LIB = @erl_interface_libpath@@DS@@erl_interface_lib@
+ERL_INTERFACE_EILIB = @erl_interface_libpath@@DS@@erl_interface_eilib@
+ERL_INTERFACE_THREADLIB = @erl_interface_threadlib@
+ERL_INTERFACE_SOCK_LIBS = @erl_interface_sock_libs@
+
+CC = @CC@
+## XXX Should set warning flag with a DEBUG_FLAG
+CFLAGS = @CFLAGS@ @DEFS@ -I$(ERL_INCLUDE) \
+ -I$(IC_INCLUDE_PATH) -I$(ERL_INTERFACE_INCLUDE)
+
+LD = @LD@
+LDFLAGS = @CROSSLDFLAGS@
+LIBS = $(IC_LIB) $(ERL_INTERFACE_LIB) $(ERL_INTERFACE_EILIB) \
+ $(ERL_INTERFACE_THREADLIB) @LIBS@ $(ERL_INTERFACE_SOCK_LIBS)
+ERLC = erlc
+
+# Generated C header files
+GEN_H_FILES = \
+ m__s.h \
+ m_i__s.h \
+ oe_erl_c_test__s.h
+
+# Generated C files
+GEN_C_FILES = \
+ m__s.c \
+ m_i__s.c \
+ oe_code_m_a.c \
+ oe_code_m_arr1.c \
+ oe_code_m_arr2.c \
+ oe_code_m_arr3.c \
+ oe_code_m_aseq.c \
+ oe_code_m_b.c \
+ oe_code_m_bseq.c \
+ oe_code_m_dd.c \
+ oe_code_m_dyn.c \
+ oe_code_m_dyn_sl.c \
+ oe_code_m_es.c \
+ oe_code_m_et.c \
+ oe_code_m_etseq.c \
+ oe_code_m_fruit.c \
+ oe_code_m_lseq.c \
+ oe_code_m_s.c \
+ oe_code_m_s_sl.c \
+ oe_code_m_sarr3.c \
+ oe_code_m_simple.c \
+ oe_code_m_ssarr3.c \
+ oe_code_m_sseq.c \
+ oe_code_m_ssstr3.c \
+ oe_code_m_sstr3.c \
+ oe_code_m_str1.c \
+ oe_code_m_str3.c \
+ oe_code_m_strRec.c \
+ oe_code_m_strRec_str5.c \
+ oe_code_m_strRec_str7.c \
+ oe_erl_c_test__s.c
+
+GEN_HRL_FILES = \
+ m.hrl \
+ m_i.hrl \
+ oe_erl_c_test.hrl
+
+GEN_ERL_FILES = \
+ m.erl \
+ m_arr2.erl \
+ m_arr3.erl \
+ m_i.erl \
+ m_str3.erl \
+ oe_erl_c_test.erl
+
+C_FILES = $(GEN_C_FILES) c_server.c callbacks.c
+
+OBJS = $(C_FILES:.c=@obj@)
+
+PGMS = c_server@exe@
+
+ERL_FILES = $(GEN_ERL_FILES) erl_client.erl
+
+EBINS = $(ERL_FILES:.erl=.@EMULATOR@)
+
+
+all: $(PGMS) $(EBINS)
+
+clean:
+ -rm -f $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \
+ $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES)
+ -del /F /Q $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \
+ $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES)
+
+$(PGMS): $(OBJS)
+ $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
+
+$(GEN_C_FILES) $(GEN_H_FILES): erl_c_test.idl
+ $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,c_server}" \
+ "+{scoped_op_calls,true}" erl_c_test.idl
+
+# If we have scoped operation calls for C, we must have that for
+# Erlang as well, if we use the m_i.erl file for calling the server.
+
+$(GEN_ERL_FILES) $(GEN_HRL_FILES): erl_c_test.idl
+ $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,erl_genserv}" \
+ "+{scoped_op_calls,true}" "+{timeout,true}" erl_c_test.idl
+
+.c@obj@:
+ $(CC) -c -o $*@obj@ $(CFLAGS) $<
+
+.erl.@EMULATOR@:
+ $(ERLC) -W -I $(IC_INCLUDE_PATH) $<
+
diff --git a/lib/ic/test/erl_client_c_server_SUITE_data/c_server.c b/lib/ic/test/erl_client_c_server_SUITE_data/c_server.c
new file mode 100644
index 0000000000..acdeff80fe
--- /dev/null
+++ b/lib/ic/test/erl_client_c_server_SUITE_data/c_server.c
@@ -0,0 +1,299 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2002-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+ */
+/* C-server for test of IC.
+ *
+ * The C-node implemented here connects to its peer node, waits for
+ * one message, evaluates the message, returns an result message, and
+ * terminates.
+ *
+ * TODO:
+ *
+ * 1. XXX #includes for VxWorks, Windows
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef __WIN32__
+# include <unistd.h>
+#endif
+
+#include <string.h>
+
+#ifdef __WIN32__
+# include <time.h>
+# include <sys/timeb.h>
+#elif defined VXWORKS
+# include <time.h>
+# include <sys/times.h>
+#else
+# include <sys/time.h>
+#endif
+
+#include <ctype.h>
+
+#ifdef __WIN32__
+# include <winsock2.h>
+# include <windows.h>
+#else
+# include <sys/types.h>
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <arpa/inet.h>
+# include <netdb.h>
+#endif
+
+#include "ic.h"
+#include "ei.h"
+#include "erl_interface.h"
+#include "eicode.h"
+#include "m_i__s.h"
+#include "m__s.h"
+
+#ifdef __WIN32__
+typedef struct {
+ long tv_sec;
+ long tv_usec;
+} MyTimeval;
+#else
+typedef struct timeval MyTimeval;
+#endif
+static void my_gettimeofday(MyTimeval *tv);
+static void showtime(MyTimeval *start, MyTimeval *stop);
+static void usage(void);
+static void done(int r);
+
+#define HOSTNAMESZ 256
+#define NODENAMESZ 512
+#define INBUFSZ 10
+#define OUTBUFSZ 0
+#define MAXTRIES 5
+
+static char *progname;
+
+/* main */
+#ifdef VXWORKS
+int c_server(int argc, char **argv)
+#else
+int main(int argc, char **argv)
+#endif
+{
+ struct hostent *hp;
+ MyTimeval start, stop;
+ int i, fd, ires, tries;
+ CORBA_Environment *env;
+ char *this_node_name = NULL;
+ char *peer_node = NULL;
+ char *cookie = NULL;
+ char host[HOSTNAMESZ + 1];
+ char this_node[NODENAMESZ + 1];
+ erlang_msg msg;
+ int status, loop;
+
+#ifdef __WIN32__
+ WORD wVersionRequested;
+ WSADATA wsaData;
+
+ wVersionRequested = MAKEWORD(2, 0);
+
+ if (WSAStartup(wVersionRequested, &wsaData) != 0) {
+ fprintf(stderr, "Could not load winsock2 v2.0 compatible DLL");
+ exit(1);
+ }
+#endif
+
+ progname = argv[0];
+ host[HOSTNAMESZ] = '\0';
+ if (gethostname(host, HOSTNAMESZ) < 0) {
+ fprintf(stderr, "Can't find own hostname\n");
+ done(1);
+ }
+ if ((hp = gethostbyname(host)) == 0) {
+ fprintf(stderr, "Can't get ip address for host %s\n", host);
+ done(1);
+ }
+ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-help") == 0) {
+ usage();
+ done(0);
+ } else if (strcmp(argv[i], "-this-node-name") == 0) {
+ i++;
+ this_node_name = argv[i];
+ } else if (strcmp(argv[i], "-peer-node") == 0) {
+ i++;
+ peer_node = argv[i];
+ } else if (strcmp(argv[i], "-cookie") == 0) {
+ i++;
+ cookie = argv[i];
+ } else {
+ fprintf(stderr, "Error : invalid argument \"%s\"\n", argv[i]);
+ usage();
+ done(1);
+ }
+ }
+
+ if (this_node_name == NULL || peer_node == NULL || cookie == NULL) {
+ fprintf(stderr, "Error: missing option\n");
+ usage();
+ done(1);
+ }
+
+ /* Behead hostname at first dot */
+ for (i=0; host[i] != '\0'; i++) {
+ if (host[i] == '.') { host[i] = '\0'; break; }
+ }
+ sprintf(this_node, "%s@%s", this_node_name, host);
+
+ fprintf(stderr, "c_server: this node: \"%s\"\n", this_node);
+ fprintf(stderr, "c_server: peer node: \"%s\"\n", peer_node);
+
+ /* initialize erl_interface */
+ erl_init(NULL, 0);
+
+ for (tries = 0; tries < MAXTRIES; tries++) {
+ /* connect to peer node */
+ ires = erl_connect_xinit(host, this_node_name, this_node,
+ (struct in_addr *)*hp->h_addr_list,
+ cookie, 0);
+ fprintf(stderr, "c_server: erl_connect_xinit(): %d\n", ires);
+
+ fd = erl_connect(peer_node);
+ fprintf(stderr, "c_server: erl_connect(): %d\n", fd);
+ if (fd >= 0)
+ break;
+ fprintf(stderr, "c_server: cannot connect, retrying\n");
+ }
+ if (fd < 0) {
+ fprintf(stderr, "c_server: cannot connect, exiting\n");
+ done(1);
+ }
+ env = CORBA_Environment_alloc(INBUFSZ, OUTBUFSZ);
+ env->_fd = fd;
+
+ status = 1;
+ loop = 1;
+ my_gettimeofday(&start);
+ while (status >= 0 && loop > 0) {
+ status = ei_receive_encoded(env->_fd, &env->_inbuf, &env->_inbufsz,
+ &msg, &env->_iin);
+ switch(status) {
+ case ERL_SEND:
+ case ERL_REG_SEND:
+ /* get result */
+ m_i__switch(NULL, env);
+ switch(env->_major) {
+ case CORBA_NO_EXCEPTION:
+ break;
+ case CORBA_SYSTEM_EXCEPTION:
+ fprintf(stderr, "Request failure, reason : %s\n",
+ (char *) CORBA_exception_value(env));
+ CORBA_exception_free(env);
+ break;
+ default: /* Should not happen */
+ CORBA_exception_free(env);
+ break;
+ }
+ /* send back result data */
+ if (env->_iout > 0)
+ ei_send_encoded(env->_fd, &env->_caller, env->_outbuf,
+ env->_iout);
+ loop = 0;
+ break;
+ case ERL_TICK:
+ break;
+ default:
+ if (status < 0) {
+ fprintf(stderr, "Status negative: %d\n", status);
+ loop = 0;
+ }
+ break;
+ }
+ }
+ my_gettimeofday(&stop);
+ showtime(&start, &stop);
+
+ erl_close_connection(fd);
+
+ CORBA_free(env->_inbuf);
+ CORBA_free(env->_outbuf);
+ CORBA_free(env);
+ if (status < 0)
+ done(-status);
+ else
+ done(0);
+}
+
+static void usage()
+{
+ fprintf(stderr, "Usage: %s [-help] -this-node-name <name> "
+ "-peer-node <nodename> -cookie <cookie>\n", progname);
+ fprintf(stderr, "Example:\n %s -this-node-name kalle "
+ "-peer-node olle@home -cookie oa678er\n", progname);
+}
+
+static void done(int r)
+{
+#ifdef __WIN32__
+ WSACleanup();
+#endif
+ exit(r);
+}
+
+static void showtime(MyTimeval *start, MyTimeval *stop)
+{
+ MyTimeval elapsed;
+
+ elapsed.tv_sec = stop->tv_sec - start->tv_sec;
+ elapsed.tv_usec = stop->tv_usec - start->tv_usec;
+ while (elapsed.tv_usec < 0) {
+ elapsed.tv_sec -= 1;
+ elapsed.tv_usec += 1000000;
+ }
+ fprintf(stderr,"%ld.%06ld seconds\n",elapsed.tv_sec, elapsed.tv_usec);
+}
+
+
+
+static void my_gettimeofday(MyTimeval *tv)
+#ifdef __WIN32__
+#define EPOCH_JULIAN_DIFF 11644473600i64
+{
+ SYSTEMTIME t;
+ FILETIME ft;
+ LONGLONG lft;
+
+ GetSystemTime(&t);
+ SystemTimeToFileTime(&t, &ft);
+ memcpy(&lft, &ft, sizeof(lft));
+ tv->tv_usec = (long) ((lft / 10i64) % 1000000i64);
+ tv->tv_sec = (long) ((lft / 10000000i64) - EPOCH_JULIAN_DIFF);
+}
+#elif defined VXWORKS
+{
+ int rate = sysClkRateGet(); /* Ticks per second */
+ unsigned long ctick = tickGet();
+ tv->tv_sec = ctick / rate; /* secs since reboot */
+ tv->tv_usec = ((ctick - (tv->tv_sec * rate))*1000000)/rate;
+}
+#else
+{
+ gettimeofday(tv, NULL);
+}
+#endif
diff --git a/lib/ic/test/erl_client_c_server_SUITE_data/callbacks.c b/lib/ic/test/erl_client_c_server_SUITE_data/callbacks.c
new file mode 100644
index 0000000000..d6b28b619d
--- /dev/null
+++ b/lib/ic/test/erl_client_c_server_SUITE_data/callbacks.c
@@ -0,0 +1,610 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2002-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#ifndef __WIN32__
+# include <unistd.h>
+#endif
+#include <string.h>
+#include <ctype.h>
+#include <ic.h>
+#include <erl_interface.h>
+#include <ei.h>
+#include "m_i__s.h"
+
+
+
+/* OK */
+
+void my_void_test(CORBA_Object oe_obj,
+ CORBA_Environment *oe_env)
+{
+ /* printf("void test !\n"); */
+}
+
+m_i_void_test__rs* m_i_void_test__cb(CORBA_Object oe_obj,
+ CORBA_Environment *oe_env)
+{
+ return (m_i_void_test__rs*) (my_void_test);
+}
+
+
+
+/* OK */
+
+void my_long_test(CORBA_Object oe_obj,
+ long* a,
+ long* b,
+ long* c,
+ CORBA_Environment *oe_env)
+{
+ /* printf("long test !\n"); */
+}
+
+
+m_i_long_test__rs* m_i_long_test__cb(CORBA_Object oe_obj,
+ long* a,
+ long* b,
+ long* c,
+ CORBA_Environment *oe_env)
+{
+ *a = *b;
+ *c = *b;
+ return (m_i_long_test__rs*) (my_long_test);
+}
+
+/* OK */
+
+void my_longlong_test(CORBA_Object oe_obj,
+ CORBA_long_long* a,
+ CORBA_long_long* b,
+ CORBA_long_long* c,
+ CORBA_Environment *oe_env)
+{
+ /* printf("long test !\n"); */
+}
+
+m_i_longlong_test__rs* m_i_longlong_test__cb(CORBA_Object oe_obj,
+ CORBA_long_long* a,
+ CORBA_long_long* b,
+ CORBA_long_long* c,
+ CORBA_Environment *oe_env)
+{
+ *a = *b;
+ *c = *b;
+ return (m_i_longlong_test__rs*) (my_longlong_test);
+}
+
+/* OK */
+void my_ulong_test(CORBA_Object oe_obj,
+ unsigned long* a,
+ unsigned long* b,
+ unsigned long* c,
+ CORBA_Environment *oe_env)
+{
+ /* printf("ulong test !\n"); */
+}
+
+m_i_ulong_test__rs* m_i_ulong_test__cb(CORBA_Object oe_obj,
+ unsigned long* a,
+ unsigned long* b,
+ unsigned long* c,
+ CORBA_Environment *oe_env)
+{
+ *a = *b;
+ *c = *b;
+ return (m_i_ulong_test__rs*) (my_ulong_test);
+}
+
+/* OK */
+void my_ulonglong_test(CORBA_Object oe_obj,
+ CORBA_unsigned_long_long* a,
+ CORBA_unsigned_long_long* b,
+ CORBA_unsigned_long_long* c,
+ CORBA_Environment *oe_env)
+{
+ /* printf("ulong test !\n"); */
+}
+
+m_i_ulonglong_test__rs* m_i_ulonglong_test__cb(CORBA_Object oe_obj,
+ CORBA_unsigned_long_long* a,
+ CORBA_unsigned_long_long* b,
+ CORBA_unsigned_long_long* c,
+ CORBA_Environment *oe_env)
+{
+ *a = *b;
+ *c = *b;
+ return (m_i_ulonglong_test__rs*) (my_ulonglong_test);
+}
+
+m_i_ushort_test__rs* m_i_ushort_test__cb(CORBA_Object oe_obj,
+ unsigned short* a,
+ unsigned short* b,
+ unsigned short* c,
+ CORBA_Environment *oe_env)
+{
+ *a = *b;
+ *c = *b;
+ return (m_i_ushort_test__rs*) NULL;
+}
+
+
+/* OK */
+void my_double_test(CORBA_Object oe_obj,
+ double* a,
+ double* b,
+ double* c,
+ CORBA_Environment *oe_env)
+{
+ /* printf("double test !\n"); */
+}
+
+m_i_double_test__rs* m_i_double_test__cb(CORBA_Object oe_obj,
+ double* a,
+ double* b,
+ double* c,
+ CORBA_Environment *oe_env)
+{
+ *a = *b;
+ *c = *b;
+ return (m_i_double_test__rs*) (my_double_test);
+}
+
+/* OK */
+m_i_char_test__rs* m_i_char_test__cb(CORBA_Object oe_obj,
+ char* a,
+ char* b,
+ char* c,
+ CORBA_Environment *oe_env)
+{
+ m_i_char_test__rs* rs = NULL;
+
+ *a = *b;
+ *c = *b;
+ return rs;
+}
+
+
+/* OK */
+m_i_wchar_test__rs* m_i_wchar_test__cb(CORBA_Object oe_obj,
+ CORBA_wchar* a,
+ CORBA_wchar* b,
+ CORBA_wchar* c,
+ CORBA_Environment *oe_env)
+{
+ m_i_wchar_test__rs* rs = NULL;
+
+ *a = *b;
+ *c = *b;
+ return rs;
+}
+
+/* OK */
+m_i_octet_test__rs* m_i_octet_test__cb(CORBA_Object oe_obj,
+ char* a,
+ char* b,
+ char* c,
+ CORBA_Environment *oe_env)
+{
+ m_i_octet_test__rs* rs = NULL;
+
+ *a = *b;
+ *c = *b;
+ return rs;
+}
+
+/* OK */
+m_i_bool_test__rs* m_i_bool_test__cb(CORBA_Object oe_obj,
+ CORBA_boolean* a,
+ CORBA_boolean* b,
+ CORBA_boolean* c,
+ CORBA_Environment *oe_env)
+{
+ m_i_bool_test__rs* rs = NULL;
+
+ *a = *b;
+ *c = *b;
+ return rs;
+}
+
+/* OK */
+void my_struct_test(CORBA_Object oe_obj,
+ m_b* a,
+ m_b* b,
+ m_b* c,
+ CORBA_Environment *oe_env)
+{
+ /* printf("struct test !\n"); */
+}
+
+m_i_struct_test__rs* m_i_struct_test__cb(CORBA_Object oe_obj,
+ m_b* a,
+ m_b* b,
+ m_b* c,
+ CORBA_Environment *oe_env)
+{
+ *a = *b;
+ *c = *b;
+ return (m_i_struct_test__rs*) (my_struct_test);
+}
+
+/* OK */
+m_i_struct2_test__rs* m_i_struct2_test__cb(CORBA_Object oe_obj,
+ m_es* a,
+ m_es* b,
+ m_es* c,
+ CORBA_Environment *oe_env)
+{
+ m_i_struct2_test__rs* rs = NULL;
+
+ *a = *b;
+ *c = *b;
+ return rs;
+}
+
+/* OK */
+/* XXX Commented out
+m_i_struct3_test__rs* m_i_struct3_test__cb(CORBA_Object oe_obj,
+ m_simple* a,
+ m_simple* b,
+ m_simple* c,
+ CORBA_Environment *oe_env)
+{
+ m_i_struct3_test__rs* rs = NULL;
+ *a = *b;
+ *c = *b;
+ return rs;
+}
+*/
+
+/* OK */
+m_i_seq1_test__rs* m_i_seq1_test__cb(CORBA_Object oe_obj,
+ m_bseq** a,
+ m_bseq* b,
+ m_bseq** c,
+ CORBA_Environment *oe_env)
+{
+ m_i_seq1_test__rs* rs = NULL;
+
+ *a = b;
+ *c = b;
+ return rs;
+}
+
+
+/* OK */
+m_i_seq2_test__rs* m_i_seq2_test__cb(CORBA_Object oe_obj,
+ m_aseq** a,
+ m_aseq* b,
+ m_aseq** c,
+ CORBA_Environment *oe_env)
+{
+ m_i_seq2_test__rs* rs = NULL;
+
+ *a = b;
+ *c = b;
+ return rs;
+}
+
+/* OK */
+m_i_seq3_test__rs* m_i_seq3_test__cb(CORBA_Object oe_obj,
+ m_lseq** a,
+ m_lseq* b,
+ m_lseq** c,
+ CORBA_Environment *oe_env)
+{
+ m_i_seq3_test__rs* rs = NULL;
+
+ *a = b;
+ *c = b;
+ return rs;
+}
+
+/* OK */
+m_i_seq4_test__rs* m_i_seq4_test__cb(CORBA_Object oe_obj,
+ m_ssstr3** a,
+ m_ssstr3* b,
+ m_ssstr3** c,
+ CORBA_Environment *oe_env)
+{
+ m_i_seq4_test__rs* rs = NULL;
+
+ *a = b;
+ *c = b;
+ return rs;
+}
+
+/* OK */
+m_i_seq5_test__rs* m_i_seq5_test__cb(CORBA_Object oe_obj,
+ m_ssarr3** a,
+ m_ssarr3* b,
+ m_ssarr3** c,
+ CORBA_Environment *oe_env)
+{
+ m_i_seq5_test__rs* rs = NULL;
+
+ *a = b;
+ *c = b;
+ return rs;
+}
+
+/* OK */
+m_i_array1_test__rs* m_i_array1_test__cb(CORBA_Object oe_obj,
+ m_arr1 a,
+ m_arr1 b,
+ m_arr1 c,
+ CORBA_Environment *oe_env)
+{
+ int i;
+ m_i_array1_test__rs* rs = NULL;
+
+ for (i = 0; i < 500; i++) {
+ a[i] = b[i];
+ c[i] = b[i];
+ }
+ return rs;
+}
+
+/* OK */
+m_i_array2_test__rs* m_i_array2_test__cb(CORBA_Object oe_obj,
+ m_dd a,
+ m_dd b,
+ m_dd c,
+ CORBA_Environment *oe_env)
+{
+ int i,j;
+ m_i_array2_test__rs* rs = NULL;
+
+ for (i = 0; i < 2; i++)
+ for (j = 0; j < 3; j++) {
+ a[i][j] = b[i][j];
+ c[i][j] = b[i][j];
+ }
+ return rs;
+}
+
+
+/* OK */
+m_i_enum_test__rs* m_i_enum_test__cb(CORBA_Object oe_obj,
+ m_fruit* a,
+ m_fruit* b,
+ m_fruit* c,
+ CORBA_Environment *oe_env)
+{
+ m_i_enum_test__rs* rs = NULL;
+
+ *a = *b;
+ *c = *b;
+ return rs;
+}
+
+/* OK */
+m_i_string1_test__rs* m_i_string1_test__cb(CORBA_Object oe_obj,
+ char ** a,
+ char * b,
+ char ** c,
+ CORBA_Environment *oe_env)
+{
+ m_i_string1_test__rs* rs = NULL;
+
+ /*printf("\nString in ------> %s\n\n",b);*/
+ *a = b;
+ *c = b;
+ return rs;
+}
+
+/* OK */
+m_i_string2_test__rs* m_i_string2_test__cb(CORBA_Object oe_obj,
+ m_sseq** a,
+ m_sseq* b,
+ m_sseq** c,
+ CORBA_Environment *oe_env)
+{
+ m_i_string2_test__rs* rs = NULL;
+
+ *a = b;
+ *c = b;
+ return rs;
+}
+
+/* OK */
+m_i_string3_test__rs* m_i_string3_test__cb(CORBA_Object oe_obj,
+ char ** a,
+ char * b,
+ char ** c,
+ CORBA_Environment *oe_env)
+{
+ m_i_string3_test__rs* rs = NULL;
+
+ *a = b;
+ *c = b;
+ return rs;
+}
+
+m_i_string4_test__rs* m_i_string4_test__cb(CORBA_Object oe_obj,
+ m_strRec** a,
+ m_strRec* b,
+ m_strRec** c,
+ CORBA_Environment *oe_env)
+{
+ *a = b;
+ *c = b;
+
+ return (m_i_string4_test__rs*) NULL;
+}
+
+/* OK */
+m_i_wstring1_test__rs* m_i_wstring1_test__cb(CORBA_Object oe_obj,
+ CORBA_wchar ** a,
+ CORBA_wchar * b,
+ CORBA_wchar ** c,
+ CORBA_Environment *oe_env)
+{
+ int tmp;
+ m_i_wstring1_test__rs* rs = NULL;
+
+ /*printf("\nString in ------> %s\n\n",b);*/
+
+ for(tmp = 0; tmp < 5; tmp++)
+ fprintf(stderr,"\np[%d] = %ld\n", tmp, b[tmp]);
+ *a = b;
+ *c = b;
+ return rs;
+}
+
+
+/* OK */
+m_i_pid_test__rs* m_i_pid_test__cb(CORBA_Object oe_obj,
+ erlang_pid* a,
+ erlang_pid* b,
+ erlang_pid* c,
+ CORBA_Environment *oe_env)
+{
+ m_i_pid_test__rs* rs = NULL;
+
+ *a = *b;
+ *c = *b;
+ return rs;
+}
+
+/* OK */
+m_i_port_test__rs* m_i_port_test__cb(CORBA_Object oe_obj,
+ erlang_port* a,
+ erlang_port* b,
+ erlang_port* c,
+ CORBA_Environment *oe_env)
+{
+ m_i_port_test__rs* rs = NULL;
+
+ strcpy((*a).node,(*b).node);
+ (*a).id = (*b).id;
+ (*a).creation = 0;
+
+ strcpy((*c).node,(*b).node);
+ (*c).id = (*b).id;
+ (*c).creation = 0;
+ return rs;
+}
+
+/* OK */
+m_i_ref_test__rs* m_i_ref_test__cb(CORBA_Object oe_obj,
+ erlang_ref* a,
+ erlang_ref* b,
+ erlang_ref* c,
+ CORBA_Environment *oe_env)
+{
+
+ m_i_ref_test__rs* rs = NULL;
+
+ strcpy((*a).node,(*b).node);
+ /*(*a).id = (*b).id;*/
+ (*a).len = (*b).len;
+ (*a).n[0] = (*b).n[0];
+ (*a).n[1] = (*b).n[1];
+ (*a).n[2] = (*b).n[2];
+ (*a).creation = 0;
+
+ strcpy((*c).node,(*b).node);
+ /*(*c).id = (*b).id;*/
+ (*c).len = (*b).len;
+ (*c).n[0] = (*b).n[0];
+ (*c).n[1] = (*b).n[1];
+ (*c).n[2] = (*b).n[2];
+ (*c).creation = 0;
+ return rs;
+}
+
+/* OK */
+m_i_term_test__rs* m_i_term_test__cb(CORBA_Object oe_obj,
+ ETERM** a,
+ ETERM** b,
+ ETERM** c,
+ CORBA_Environment *oe_env)
+{
+ m_i_term_test__rs* rs = NULL;
+
+ *a = *b;
+ *c = *b;
+ return rs;
+}
+
+m_i_typedef_test__rs* m_i_typedef_test__cb(CORBA_Object oe_obj,
+ long* a,
+ ETERM** b,
+ erlang_port* c,
+ ETERM** d ,
+ erlang_port* e,
+ CORBA_Environment *oe_env)
+{
+ m_i_typedef_test__rs* rs = NULL;
+
+ *d = *b;
+ strcpy((*e).node,(*c).node);
+ (*e).id = (*c).id;
+ (*e).creation = 0;
+ *a = 4711;
+ return rs;
+}
+
+/* OK */
+m_i_inline_sequence_test__rs* m_i_inline_sequence_test__cb(
+ CORBA_Object oe_obj,
+ m_s** a,
+ m_s* b,
+ m_s** c,
+ CORBA_Environment *oe_env)
+{
+ m_i_inline_sequence_test__rs* rs = NULL;
+
+ *a = b;
+ *c = b;
+ return rs;
+}
+
+/* OK */
+m_i_term_sequence_test__rs* m_i_term_sequence_test__cb(
+ CORBA_Object oe_obj,
+ m_etseq** a,
+ m_etseq* b,
+ m_etseq** c,
+ CORBA_Environment *oe_env)
+{
+ m_i_term_sequence_test__rs* rs = NULL;
+
+ *a = b;
+ *c = b;
+ return rs;
+}
+
+
+/* OK */
+m_i_term_struct_test__rs* m_i_term_struct_test__cb(CORBA_Object oe_obj,
+ m_et* a,
+ m_et* b,
+ m_et* c,
+ CORBA_Environment *oe_env)
+{
+ m_i_term_struct_test__rs* rs = NULL;
+
+ *a = *b;
+ *c = *b;
+ return rs;
+}
+
diff --git a/lib/ic/test/erl_client_c_server_SUITE_data/erl_c_test.idl b/lib/ic/test/erl_client_c_server_SUITE_data/erl_c_test.idl
new file mode 100644
index 0000000000..963bc69017
--- /dev/null
+++ b/lib/ic/test/erl_client_c_server_SUITE_data/erl_c_test.idl
@@ -0,0 +1,174 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 2002-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+#include "erlang.idl"
+
+
+const short TestConst = 1;
+
+module m {
+
+ const short TestConst = 2;
+
+ struct b {
+ long l;
+ char c;
+ };
+
+ struct simple {
+ long l;
+ b b_t;
+ };
+
+ enum fruit {orange, banana, apple, peach, pear};
+
+ typedef sequence<long> lseq;
+
+ typedef sequence<b> bseq;
+
+ struct a {
+ long l;
+ bseq y;
+ double d;
+ };
+
+ typedef sequence<a> aseq;
+
+ typedef sequence<string> sseq;
+ typedef string str;
+ typedef long myLong;
+
+ typedef long arr1[500], dd[2][3];
+
+ typedef erlang::term apa;
+ typedef erlang::port banan;
+
+ typedef sequence<erlang::term> etseq;
+
+ struct s {
+ long l;
+ sequence<long> sl;
+ };
+
+ struct es {
+ fruit f;
+ myLong l;
+ };
+
+ struct et {
+ erlang::term e;
+ long l;
+ };
+
+
+ typedef sequence<char> str1;
+ typedef string<12> str2;
+ typedef char str3[3];
+
+ typedef sequence<string> sstr3; // sequence of string
+ typedef sequence<sstr3> ssstr3; // sequence of sequences of strings
+
+ typedef long arr3[3]; // array of long
+ typedef sequence<arr3> sarr3; // sequence of array
+ typedef sequence<sarr3> ssarr3; // sequence of sequnces of arrays of strings
+
+ struct strRec{
+ boolean bb;
+ string str4;
+ long str7[3][2];
+ sequence<char> str5;
+ string<12> str6;
+ str3 str8;
+ str2 str9;
+ str1 str10;
+ };
+
+
+ struct dyn {
+ long l;
+ sequence<long> sl;
+ };
+ typedef dyn arr2[1][2];
+
+
+ interface i {
+
+ const short TestConst = 3;
+
+ //arr2 suck(in arr2 x, out arr2 y );
+
+ ///////////////////////////////// attribute long l;
+
+ // simple types
+ void void_test();
+ long long_test(in long a, out long a1);
+ long long longlong_test(in long long a, out long long a1);
+ unsigned short ushort_test(in unsigned short a, out unsigned short a1);
+ unsigned long ulong_test(in unsigned long a, out unsigned long a1);
+ unsigned long long ulonglong_test(in unsigned long long a, out unsigned long long a1);
+ double double_test(in double a, out double a1);
+ char char_test(in char a, out char a1);
+ wchar wchar_test(in wchar a, out wchar a1);
+ octet octet_test(in octet a, out octet a1);
+ boolean bool_test(in boolean a, out boolean a1);
+
+ // Seq. and struct tests
+ b struct_test(in b a, out b a1);
+ es struct2_test(in es a, out es a1);
+ //simple struct3_test(in simple x, out simple y);
+ bseq seq1_test(in bseq a, out bseq a1);
+ aseq seq2_test(in aseq a, out aseq a1);
+ lseq seq3_test(in lseq a, out lseq a1);
+ ssstr3 seq4_test(in ssstr3 a, out ssstr3 a1);
+ ssarr3 seq5_test(in ssarr3 a, out ssarr3 a1);
+
+ // Array tests
+ arr1 array1_test(in arr1 a, out arr1 a1);
+ dd array2_test(in dd a, out dd a1);
+
+ // enum test
+ fruit enum_test(in fruit a, out fruit a1);
+
+ // string tests
+ string string1_test(in string a, out string a1);
+ wstring wstring1_test(in wstring a, out wstring a1);
+ sseq string2_test(in sseq a, out sseq a1);
+ str string3_test(in str a, out str a1);
+ strRec string4_test(in strRec a, out strRec a1);
+
+ // Special erlang types
+ erlang::pid pid_test(in erlang::pid a, out erlang::pid a1);
+ erlang::port port_test(in erlang::port a, out erlang::port a1);
+ erlang::ref ref_test(in erlang::ref a, out erlang::ref a1);
+ erlang::term term_test(in erlang::term a, out erlang::term a1);
+
+ // typedef test
+ long typedef_test(in apa a, in banan b, out apa a1, out banan b1);
+
+ // inlined seq. test
+ s inline_sequence_test(in s a, out s a1);
+
+ // term seq. test
+ etseq term_sequence_test(in etseq a, out etseq a1);
+ // term struct test
+ et term_struct_test(in et a, out et a1);
+
+ };
+
+};
diff --git a/lib/ic/test/erl_client_c_server_SUITE_data/erl_client.erl b/lib/ic/test/erl_client_c_server_SUITE_data/erl_client.erl
new file mode 100644
index 0000000000..79ec28a921
--- /dev/null
+++ b/lib/ic/test/erl_client_c_server_SUITE_data/erl_client.erl
@@ -0,0 +1,331 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+-module(erl_client).
+
+-export([void_test/2, long_test/2, longlong_test/2, ushort_test/2,
+ ulong_test/2, ulonglong_test/2, double_test/2, char_test/2,
+ wchar_test/2, octet_test/2, bool_test/2, struct_test/2,
+ struct2_test/2, seq1_test/2, seq2_test/2, seq3_test/2,
+ seq4_test/2, seq5_test/2, array1_test/2, array2_test/2,
+ enum_test/2, string1_test/2, wstring1_test/2, string2_test/2,
+ string3_test/2, string4_test/2, pid_test/2, port_test/2,
+ ref_test/2, term_test/2, typedef_test/2,
+ inline_sequence_test/2, term_sequence_test/2,
+ term_struct_test/2
+
+]).
+
+-include("m.hrl").
+-include("m_i.hrl").
+-include("oe_erl_c_test.hrl").
+
+%%b
+void_test(Node, Timeout) ->
+ Ret = m_i:void_test({olsson, Node}, Timeout),
+ Ret == void. % XXX Not documented
+%%e
+
+%%b
+long_test(Node, Timeout) ->
+ In = max_long(),
+ {Ret, Out} = m_i:long_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+longlong_test(Node, Timeout) ->
+ In = 65537,
+ {Ret, Out} = m_i:longlong_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+ushort_test(Node, Timeout) ->
+ In = max_ushort(),
+ {Ret, Out} = m_i:ushort_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+ulong_test(Node, Timeout) ->
+ In = max_ulong(),
+ {Ret, Out} = m_i:ulong_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+ulonglong_test(Node, Timeout) ->
+ In = 65537,
+ {Ret, Out} = m_i:ulonglong_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+double_test(Node, Timeout) ->
+ In = 37768.93,
+ {Ret, Out} = m_i:double_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+char_test(Node, Timeout) ->
+ In = 80,
+ {Ret, Out} = m_i:char_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+wchar_test(Node, Timeout) ->
+ In = 4097,
+ {Ret, Out} = m_i:wchar_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+octet_test(Node, Timeout) ->
+ In = 255,
+ {Ret, Out} = m_i:octet_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+bool_test(Node, Timeout) ->
+ In = false,
+ {Ret, Out} = m_i:bool_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+struct_test(Node, Timeout) ->
+ In = #m_b{l = max_long(), c = $a},
+ {Ret, Out} = m_i:struct_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+struct2_test(Node, Timeout) ->
+ In = #m_es{ f = banana, l = max_long()},
+ {Ret, Out} = m_i:struct2_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+seq1_test(Node, Timeout) ->
+ B1 = #m_b{l = max_long(), c = $a},
+ B2 = #m_b{l = min_long(), c = $b},
+ In = [B1, B2],
+ {Ret, Out} = m_i:seq1_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+seq2_test(Node, Timeout) ->
+ B = #m_b{l = max_long(), c = $a},
+ A = #m_a{l = min_long(), y = [B, B], d = 4711.31},
+ In = [A, A, A],
+ {Ret, Out} = m_i:seq2_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+seq3_test(Node, Timeout) ->
+ In = [max_long(), min_long(), max_long()],
+ {Ret, Out} = m_i:seq3_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+seq4_test(Node, Timeout) ->
+ In = [["hello", "all"], ["Erlang", "users", "!"]],
+ {Ret, Out} = m_i:seq4_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+seq5_test(Node, Timeout) ->
+ Arr3 = mk_array(3, max_long()),
+ In = [[Arr3, Arr3], [Arr3, Arr3, Arr3]],
+ {Ret, Out} = m_i:seq5_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+array1_test(Node, Timeout) ->
+ In = mk_array(500, min_long()),
+ {Ret, Out} = m_i:array1_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+array2_test(Node, Timeout) ->
+ In = mk_array(2, mk_array(3, min_long())),
+ {Ret, Out} = m_i:array2_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+enum_test(Node, Timeout) ->
+ In = banana,
+ {Ret, Out} = m_i:enum_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+string1_test(Node, Timeout) ->
+ In = "Developing Erlang applications is fun!",
+ {Ret, Out} = m_i:string1_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+wstring1_test(Node, Timeout) ->
+ In = [1047| "eveloping Erlang applications is fun!"],
+ {Ret, Out} = m_i:wstring1_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+string2_test(Node, Timeout) ->
+ In = ["Developing Erlang applications ", "is fun!"],
+ {Ret, Out} = m_i:string2_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+string3_test(Node, Timeout) ->
+ In = "Developing Erlang applications is fun!",
+ {Ret, Out} = m_i:string3_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+string4_test(Node, Timeout) ->
+
+ In = #m_strRec{
+ bb = true,
+ str4 = "Developing Erlang applications "
+ "is fun!",
+ str7 = mk_array(3, mk_array(2, max_long())),
+ str5 = [$a, $b, $c, $d, $e, $f],
+ str6 = "123456789012",
+ str8 = {$x, $y, $x},
+ str9 = "123456789012",
+ str10 = [$a, $b, $c, $d, $e, $f]
+ },
+ {Ret, Out} = m_i:string4_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+pid_test(Node, Timeout) ->
+ In = self(),
+ {Ret, Out} = m_i:pid_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+port_test(Node, Timeout) ->
+ In = get(port_test_port),
+ {Ret, Out} = m_i:port_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+ref_test(Node, Timeout) ->
+ In = make_ref(),
+ {Ret, Out} = m_i:ref_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+term_test(Node, Timeout) ->
+ In = {[a, b], 17, kalle},
+ {Ret, Out} = m_i:term_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+typedef_test(Node, Timeout) ->
+ In1 = {nisse, [1, 2], olsson},
+ In2 = get(port_test_port),
+ {Ret, Out1, Out2} = m_i:typedef_test({olsson, Node}, Timeout, In1, In2),
+ %% XXX Should check that Ret is an integer.
+ (Out1 == In1) and (Out2 == In2).
+%%e
+
+%%b
+inline_sequence_test(Node, Timeout) ->
+ In = #m_s{l = min_long(), sl = [max_long(), min_long()]},
+ {Ret, Out} = m_i:inline_sequence_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+term_sequence_test(Node, Timeout) ->
+ In = lists:duplicate(17, {nisse, [1, 2], {kalle, olsson}}),
+ {Ret, Out} = m_i:term_sequence_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+term_struct_test(Node, Timeout) ->
+ In = #m_et{e = {nisse, ["abcde"], {kalle, olsson}}, l = 4711},
+ {Ret, Out} = m_i:term_struct_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+
+%% Locals
+
+mk_array(Es) ->
+ list_to_tuple(Es).
+
+mk_array(N, E) ->
+ mk_array(lists:duplicate(N, E)).
+
+%% max_short() ->
+%% power_of_two(15) - 1.
+max_long() ->
+ power_of_two(31) - 1.
+max_longlong() ->
+ power_of_two(63) - 1.
+max_ushort() ->
+ power_of_two(16) - 1.
+max_ulong() ->
+ power_of_two(32) - 1.
+max_ulonglong() ->
+ power_of_two(64) - 1.
+
+%% min_short() ->
+%% -power_of_two(15).
+min_long() ->
+ -power_of_two(31).
+%% min_longlong() ->
+%% -power_of_two(63).
+%% min_ushort() ->
+%% 0.
+%% min_ulong() ->
+%% 0.
+%% min_ulonglong() ->
+%% 0.
+
+power_of_two(N) ->
+ round(math:pow(2, N)).
+
diff --git a/lib/ic/test/erl_client_c_server_proto_SUITE.erl b/lib/ic/test/erl_client_c_server_proto_SUITE.erl
new file mode 100644
index 0000000000..d75feb621a
--- /dev/null
+++ b/lib/ic/test/erl_client_c_server_proto_SUITE.erl
@@ -0,0 +1,350 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+
+%%----------------------------------------------------------------------
+%% Purpose : Test suite for erl-client/c-server
+%%----------------------------------------------------------------------
+
+
+-module(erl_client_c_server_proto_SUITE).
+-include("test_server.hrl").
+
+-export([init_per_testcase/2, fin_per_testcase/2, all/1, void_test/1,
+ long_test/1, longlong_test/1, ushort_test/1, ulong_test/1,
+ ulonglong_test/1, double_test/1, char_test/1, wchar_test/1,
+ octet_test/1, bool_test/1, struct_test/1, struct2_test/1,
+ seq1_test/1, seq2_test/1, seq3_test/1, seq4_test/1,
+ seq5_test/1, array1_test/1, array2_test/1, enum_test/1,
+ string1_test/1, string2_test/1, string3_test/1,
+ string4_test/1, pid_test/1, port_test/1, ref_test/1,
+ term_test/1, typedef_test/1, inline_sequence_test/1,
+ term_sequence_test/1, term_struct_test/1, wstring1_test/1]).
+
+-define(DEFAULT_TIMEOUT, 20000).
+-define(PORT_TIMEOUT, 15000).
+-define(CALL_TIMEOUT, 5000).
+
+-define(C_SERVER_NODE_NAME, idl_c_server_test).
+
+%% Add/remove code path and watchdog before/after each test case.
+%%
+init_per_testcase(_Case, Config) ->
+ DataDir = ?config(data_dir, Config),
+ code:add_patha(DataDir),
+
+ %% Since other test suites use the module m_i, we have
+ %% to make sure we are using the right m_i module.
+ code:purge(m_i),
+ code:load_file(m_i),
+
+ WatchDog = test_server:timetrap(?DEFAULT_TIMEOUT),
+ [{watchdog, WatchDog}| Config].
+
+fin_per_testcase(_Case, Config) ->
+ DataDir = ?config(data_dir, Config),
+ code:del_path(DataDir),
+ WatchDog = ?config(watchdog, Config),
+ test_server:timetrap_cancel(WatchDog).
+
+all(doc) ->
+ "Test of IC with an Erlang client and a C server. "
+ "The communication is via Erlang distribution.";
+all(suite) ->
+ [void_test, long_test, longlong_test, ushort_test,
+ ulong_test, ulonglong_test, double_test,
+ char_test, wchar_test, octet_test, bool_test, struct_test,
+ struct2_test, seq1_test, seq2_test, seq3_test, seq4_test,
+ seq5_test, array1_test, array2_test, enum_test, string1_test,
+ string2_test, string3_test, string4_test, pid_test, port_test,
+ ref_test, term_test, typedef_test, inline_sequence_test,
+ term_sequence_test, term_struct_test, wstring1_test].
+
+
+array1_test(doc) -> "";
+array1_test(suite) -> [];
+array1_test(Config) ->
+ do_test(array1_test, Config).
+
+array2_test(doc) -> "";
+array2_test(suite) -> [];
+array2_test(Config) ->
+ do_test(array2_test, Config).
+
+bool_test(doc) -> "";
+bool_test(suite) -> [];
+bool_test(Config) ->
+ do_test(bool_test, Config).
+
+char_test(doc) -> "";
+char_test(suite) -> [];
+char_test(Config) ->
+ do_test(char_test, Config).
+
+double_test(doc) -> "";
+double_test(suite) -> [];
+double_test(Config) ->
+ do_test(double_test, Config).
+
+enum_test(doc) -> "";
+enum_test(suite) -> [];
+enum_test(Config) ->
+ do_test(enum_test, Config).
+
+inline_sequence_test(doc) -> "";
+inline_sequence_test(suite) -> [];
+inline_sequence_test(Config) ->
+ do_test(inline_sequence_test, Config).
+
+longlong_test(doc) -> "";
+longlong_test(suite) -> [];
+longlong_test(Config) ->
+ do_test(longlong_test, Config).
+
+long_test(doc) -> "";
+long_test(suite) -> [];
+long_test(Config) ->
+ do_test(long_test, Config).
+
+octet_test(doc) -> "";
+octet_test(suite) -> [];
+octet_test(Config) ->
+ do_test(octet_test, Config).
+
+pid_test(doc) -> "";
+pid_test(suite) -> [];
+pid_test(Config) ->
+ do_test(pid_test, Config).
+
+port_test(doc) -> "";
+port_test(suite) -> [];
+port_test(Config) ->
+ do_test(port_test, Config).
+
+ref_test(doc) -> "";
+ref_test(suite) -> [];
+ref_test(Config) ->
+ do_test(ref_test, Config).
+
+seq1_test(doc) -> "";
+seq1_test(suite) -> [];
+seq1_test(Config) ->
+ do_test(seq1_test, Config).
+
+seq2_test(doc) -> "";
+seq2_test(suite) -> [];
+seq2_test(Config) ->
+ do_test(seq2_test, Config).
+
+seq3_test(doc) -> "";
+seq3_test(suite) -> [];
+seq3_test(Config) ->
+ do_test(seq3_test, Config).
+
+seq4_test(doc) -> "";
+seq4_test(suite) -> [];
+seq4_test(Config) ->
+ do_test(seq4_test, Config).
+
+seq5_test(doc) -> "";
+seq5_test(suite) -> [];
+seq5_test(Config) ->
+ do_test(seq5_test, Config).
+
+string1_test(doc) -> "";
+string1_test(suite) -> [];
+string1_test(Config) ->
+ do_test(string1_test, Config).
+
+string2_test(doc) -> "";
+string2_test(suite) -> [];
+string2_test(Config) ->
+ do_test(string2_test, Config).
+
+string3_test(doc) -> "";
+string3_test(suite) -> [];
+string3_test(Config) ->
+ do_test(string3_test, Config).
+
+string4_test(doc) -> "";
+string4_test(suite) -> [];
+string4_test(Config) ->
+ do_test(string4_test, Config).
+
+struct2_test(doc) -> "";
+struct2_test(suite) -> [];
+struct2_test(Config) ->
+ do_test(struct2_test, Config).
+
+struct_test(doc) -> "";
+struct_test(suite) -> [];
+struct_test(Config) ->
+ do_test(struct_test, Config).
+
+term_sequence_test(doc) -> "";
+term_sequence_test(suite) -> [];
+term_sequence_test(Config) ->
+ do_test(term_sequence_test, Config).
+
+term_struct_test(doc) -> "";
+term_struct_test(suite) -> [];
+term_struct_test(Config) ->
+ do_test(term_struct_test, Config).
+
+term_test(doc) -> "";
+term_test(suite) -> [];
+term_test(Config) ->
+ do_test(term_test, Config).
+
+typedef_test(doc) -> "";
+typedef_test(suite) -> [];
+typedef_test(Config) ->
+ do_test(typedef_test, Config).
+
+ulonglong_test(doc) -> "";
+ulonglong_test(suite) -> [];
+ulonglong_test(Config) ->
+ do_test(ulonglong_test, Config).
+
+ulong_test(doc) -> "";
+ulong_test(suite) -> [];
+ulong_test(Config) ->
+ do_test(ulong_test, Config).
+
+ushort_test(doc) -> "";
+ushort_test(suite) -> [];
+ushort_test(Config) ->
+ do_test(ushort_test, Config).
+
+void_test(doc) -> "";
+void_test(suite) -> [];
+void_test(Config) ->
+ do_test(void_test, Config).
+
+wchar_test(doc) -> "";
+wchar_test(suite) -> [];
+wchar_test(Config) ->
+ do_test(wchar_test, Config).
+
+wstring1_test(doc) -> "";
+wstring1_test(suite) -> [];
+wstring1_test(Config) ->
+ do_test(wstring1_test, Config).
+
+
+do_test(Case, Config) ->
+ %% Trap exits
+ process_flag(trap_exit, true),
+ Node = atom_to_list(node()),
+ [_NodeName, HostName] = string:tokens(Node, "@"),
+ DataDir = ?config(data_dir, Config),
+ %% io:format("~p: data directory: ~p~n", [?MODULE, DataDir]),
+ Cookie = atom_to_list(erlang:get_cookie()),
+ ServerNodeName = atom_to_list(?C_SERVER_NODE_NAME),
+ %% Start C-server node as a port program. We wait for the node
+ %% to connect to us.
+ Cmd = filename:join([DataDir, "c_server"]) ++
+ " -this-node-name " ++ ServerNodeName ++
+ " -peer-node " ++ Node ++
+ " -cookie " ++ Cookie,
+ Port = open_port({spawn, Cmd}, [exit_status, eof, stderr_to_stdout]),
+ ServerNode = list_to_atom(ServerNodeName ++ "@" ++ HostName),
+ Res = case wait_for_hidden_node(ServerNode) of
+ ok ->
+ %% Need a port for port_test and typedef_test
+ put(port_test_port, Port),
+ R = (catch erl_client:Case(ServerNode, ?CALL_TIMEOUT)),
+ case wait_for_completion(Port) of
+ {error, timeout} ->
+ kill_off_node(ServerNode);
+ _ ->
+ ok
+ end,
+ R;
+ {error, timeout} ->
+ case wait_for_completion(Port) of
+ {error, timeout} ->
+ kill_off_node(ServerNode);
+ _ ->
+ ok
+ end,
+ {error, timeout}
+ end,
+ process_flag(trap_exit, false),
+ true = Res.
+
+
+%% Wait for eof *and* exit status, but return if exit status indicates
+%% an error, or we have been waiting more than PORT_TIMEOUT seconds.
+%%
+wait_for_completion(Port) ->
+ wait_for_completion(Port, 0).
+
+wait_for_completion(Port, N) when N < 2 ->
+ receive
+ {Port, {data, Bytes}} ->
+ %% Relay output
+ io:format("~s", [Bytes]),
+ wait_for_completion(Port, N);
+ {Port, {exit_status, 0}} ->
+ wait_for_completion(Port, N + 1);
+ {Port, {exit_status, Status}} ->
+ {error, Status};
+ {Port, eof} ->
+ wait_for_completion(Port, N + 1);
+ {'EXIT', Port, Reason} ->
+ io:format("Port exited with reason: ~w~n", [Reason]),
+ wait_for_completion(Port, N);
+ {'EXIT', From, Reason} ->
+ io:format("Got unexpected exit: ~p~n", [{'EXIT', From, Reason}]),
+ wait_for_completion(Port, N)
+ after ?PORT_TIMEOUT ->
+ {error, timeout}
+ end;
+wait_for_completion(_, _) ->
+ ok.
+
+wait_for_hidden_node(Node) ->
+ Times = ?DEFAULT_TIMEOUT div 100,
+ wait_for_hidden_node(Node, Times, 100).
+
+wait_for_hidden_node(Node, Times, WaitTime) when Times > 0 ->
+ io:format("Waiting for hidden node: ~p~n", [Node]),
+ case lists:member(Node, erlang:nodes(hidden)) of
+ true ->
+ ok;
+ false ->
+ delay(WaitTime),
+ wait_for_hidden_node(Node, Times - 1, WaitTime)
+ end;
+wait_for_hidden_node(_Node, _, _WaitTime) ->
+ {error, timeout}.
+
+kill_off_node(Node) ->
+ catch rpc:cast(Node, erlang, halt, [1]).
+
+delay(Time) ->
+ receive
+ after Time ->
+ ok
+ end.
+
+
+
+
diff --git a/lib/ic/test/erl_client_c_server_proto_SUITE_data/Makefile.src b/lib/ic/test/erl_client_c_server_proto_SUITE_data/Makefile.src
new file mode 100644
index 0000000000..b7e7ee77d0
--- /dev/null
+++ b/lib/ic/test/erl_client_c_server_proto_SUITE_data/Makefile.src
@@ -0,0 +1,150 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2004-2009. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+#
+# Makefile.src for erl_client_c_server test
+# Note: This file *must* work for both Unix and Windows
+#
+# We use both `rm' (Unix) and `del' (Windows) for removing files, but
+# with a `-' in front so that the error in not finding `rm' (`del') on
+# Windows (Unix) is ignored.
+#
+# VxWorks? XXX
+#
+
+.SUFFIXES:
+.SUFFIXES: .c .h .erl .idl @obj@ .@EMULATOR@
+
+
+# Variables from ts:
+#
+
+ERL_INCLUDE = @erl_include@
+
+IC_INCLUDE_PATH = @ic_include_path@
+IC_LIB = @ic_libpath@@DS@@ic_lib@
+
+ERL_INTERFACE_INCLUDE = @erl_interface_include@
+ERL_INTERFACE_LIB = @erl_interface_libpath@@DS@@erl_interface_lib@
+ERL_INTERFACE_EILIB = @erl_interface_libpath@@DS@@erl_interface_eilib@
+ERL_INTERFACE_THREADLIB = @erl_interface_threadlib@
+ERL_INTERFACE_SOCK_LIBS = @erl_interface_sock_libs@
+
+CC = @CC@
+## XXX Should set warning flag with a DEBUG_FLAG
+CFLAGS = @CFLAGS@ @DEFS@ -I$(ERL_INCLUDE) \
+ -I$(IC_INCLUDE_PATH) -I$(ERL_INTERFACE_INCLUDE)
+
+LD = @LD@
+LDFLAGS = @CROSSLDFLAGS@
+LIBS = $(IC_LIB) $(ERL_INTERFACE_LIB) $(ERL_INTERFACE_EILIB) \
+ $(ERL_INTERFACE_THREADLIB) @LIBS@ $(ERL_INTERFACE_SOCK_LIBS)
+ERLC = erlc
+
+# Generated C header files
+GEN_H_FILES = \
+ m__s.h \
+ m_i__s.h \
+ oe_erl_c_test__s.h
+
+# Generated C files
+GEN_C_FILES = \
+ m__s.c \
+ m_i__s.c \
+ oe_code_m_a.c \
+ oe_code_m_arr1.c \
+ oe_code_m_arr2.c \
+ oe_code_m_arr3.c \
+ oe_code_m_aseq.c \
+ oe_code_m_b.c \
+ oe_code_m_bseq.c \
+ oe_code_m_dd.c \
+ oe_code_m_dyn.c \
+ oe_code_m_dyn_sl.c \
+ oe_code_m_es.c \
+ oe_code_m_et.c \
+ oe_code_m_etseq.c \
+ oe_code_m_fruit.c \
+ oe_code_m_lseq.c \
+ oe_code_m_s.c \
+ oe_code_m_s_sl.c \
+ oe_code_m_sarr3.c \
+ oe_code_m_simple.c \
+ oe_code_m_ssarr3.c \
+ oe_code_m_sseq.c \
+ oe_code_m_ssstr3.c \
+ oe_code_m_sstr3.c \
+ oe_code_m_str1.c \
+ oe_code_m_str3.c \
+ oe_code_m_strRec.c \
+ oe_code_m_strRec_str5.c \
+ oe_code_m_strRec_str7.c \
+ oe_erl_c_test__s.c
+
+GEN_HRL_FILES = \
+ m.hrl \
+ m_i.hrl \
+ oe_erl_c_test.hrl
+
+GEN_ERL_FILES = \
+ m.erl \
+ m_arr2.erl \
+ m_arr3.erl \
+ m_i.erl \
+ m_str3.erl \
+ oe_erl_c_test.erl
+
+C_FILES = $(GEN_C_FILES) c_server.c callbacks.c
+
+OBJS = $(C_FILES:.c=@obj@)
+
+PGMS = c_server@exe@
+
+ERL_FILES = $(GEN_ERL_FILES) erl_client.erl
+
+EBINS = $(ERL_FILES:.erl=.@EMULATOR@)
+
+
+all: $(PGMS) $(EBINS)
+
+clean:
+ -rm -f $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \
+ $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES)
+ -del /F /Q $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \
+ $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES)
+
+$(PGMS): $(OBJS)
+ $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
+
+$(GEN_C_FILES) $(GEN_H_FILES): erl_c_test.idl
+ $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,c_server}" \
+ "+{scoped_op_calls,true}" erl_c_test.idl
+
+# If we have scoped operation calls for C, we must have that for
+# Erlang as well, if we use the m_i.erl file for calling the server.
+
+$(GEN_ERL_FILES) $(GEN_HRL_FILES): erl_c_test.idl
+ $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,erl_genserv}" \
+ "+{scoped_op_calls,true}" "+{timeout,true}" erl_c_test.idl
+
+.c@obj@:
+ $(CC) -c -o $*@obj@ $(CFLAGS) $<
+
+.erl.@EMULATOR@:
+ $(ERLC) -W -I $(IC_INCLUDE_PATH) $<
+
diff --git a/lib/ic/test/erl_client_c_server_proto_SUITE_data/c_server.c b/lib/ic/test/erl_client_c_server_proto_SUITE_data/c_server.c
new file mode 100644
index 0000000000..329f444112
--- /dev/null
+++ b/lib/ic/test/erl_client_c_server_proto_SUITE_data/c_server.c
@@ -0,0 +1,299 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2004-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+ */
+/* C-server for test of IC.
+ *
+ * The C-node implemented here connects to its peer node, waits for
+ * one message, evaluates the message, returns an result message, and
+ * terminates.
+ *
+ * TODO:
+ *
+ * 1. XXX #includes for VxWorks, Windows
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef __WIN32__
+# include <unistd.h>
+#endif
+
+#include <string.h>
+
+#ifdef __WIN32__
+# include <time.h>
+# include <sys/timeb.h>
+#elif defined VXWORKS
+# include <time.h>
+# include <sys/times.h>
+#else
+# include <sys/time.h>
+#endif
+
+#include <ctype.h>
+
+#ifdef __WIN32__
+# include <winsock2.h>
+# include <windows.h>
+#else
+# include <sys/types.h>
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <arpa/inet.h>
+# include <netdb.h>
+#endif
+
+#include "ic.h"
+#include "ei.h"
+#include "erl_interface.h"
+#include "eicode.h"
+#include "m_i__s.h"
+#include "m__s.h"
+
+#ifdef __WIN32__
+typedef struct {
+ long tv_sec;
+ long tv_usec;
+} MyTimeval;
+#else
+typedef struct timeval MyTimeval;
+#endif
+static void my_gettimeofday(MyTimeval *tv);
+static void showtime(MyTimeval *start, MyTimeval *stop);
+static void usage(void);
+static void done(int r);
+
+#define HOSTNAMESZ 256
+#define NODENAMESZ 512
+#define INBUFSZ 10
+#define OUTBUFSZ 0
+#define MAXTRIES 5
+
+static char *progname;
+
+/* main */
+#ifdef VXWORKS
+int c_server(int argc, char **argv)
+#else
+int main(int argc, char **argv)
+#endif
+{
+ struct hostent *hp;
+ MyTimeval start, stop;
+ int i, fd, ires, tries;
+ CORBA_Environment *env;
+ char *this_node_name = NULL;
+ char *peer_node = NULL;
+ char *cookie = NULL;
+ char host[HOSTNAMESZ + 1];
+ char this_node[NODENAMESZ + 1];
+ erlang_msg msg;
+ int status, loop;
+
+#ifdef __WIN32__
+ WORD wVersionRequested;
+ WSADATA wsaData;
+
+ wVersionRequested = MAKEWORD(2, 0);
+
+ if (WSAStartup(wVersionRequested, &wsaData) != 0) {
+ fprintf(stderr, "Could not load winsock2 v2.0 compatible DLL");
+ exit(1);
+ }
+#endif
+
+ progname = argv[0];
+ host[HOSTNAMESZ] = '\0';
+ if (gethostname(host, HOSTNAMESZ) < 0) {
+ fprintf(stderr, "Can't find own hostname\n");
+ done(1);
+ }
+ if ((hp = gethostbyname(host)) == 0) {
+ fprintf(stderr, "Can't get ip address for host %s\n", host);
+ done(1);
+ }
+ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-help") == 0) {
+ usage();
+ done(0);
+ } else if (strcmp(argv[i], "-this-node-name") == 0) {
+ i++;
+ this_node_name = argv[i];
+ } else if (strcmp(argv[i], "-peer-node") == 0) {
+ i++;
+ peer_node = argv[i];
+ } else if (strcmp(argv[i], "-cookie") == 0) {
+ i++;
+ cookie = argv[i];
+ } else {
+ fprintf(stderr, "Error : invalid argument \"%s\"\n", argv[i]);
+ usage();
+ done(1);
+ }
+ }
+
+ if (this_node_name == NULL || peer_node == NULL || cookie == NULL) {
+ fprintf(stderr, "Error: missing option\n");
+ usage();
+ done(1);
+ }
+
+ /* Behead hostname at first dot */
+ for (i=0; host[i] != '\0'; i++) {
+ if (host[i] == '.') { host[i] = '\0'; break; }
+ }
+ sprintf(this_node, "%s@%s", this_node_name, host);
+
+ fprintf(stderr, "c_server: this node: \"%s\"\n", this_node);
+ fprintf(stderr, "c_server: peer node: \"%s\"\n", peer_node);
+
+ /* initialize erl_interface */
+ erl_init(NULL, 0);
+
+ for (tries = 0; tries < MAXTRIES; tries++) {
+ /* connect to peer node */
+ ires = erl_connect_xinit(host, this_node_name, this_node,
+ (struct in_addr *)*hp->h_addr_list,
+ cookie, 0);
+ fprintf(stderr, "c_server: erl_connect_xinit(): %d\n", ires);
+
+ fd = erl_connect(peer_node);
+ fprintf(stderr, "c_server: erl_connect(): %d\n", fd);
+ if (fd >= 0)
+ break;
+ fprintf(stderr, "c_server: cannot connect, retrying\n");
+ }
+ if (fd < 0) {
+ fprintf(stderr, "c_server: cannot connect, exiting\n");
+ done(1);
+ }
+ env = CORBA_Environment_alloc(INBUFSZ, OUTBUFSZ);
+ env->_fd = fd;
+
+ status = 1;
+ loop = 1;
+ my_gettimeofday(&start);
+ while (status >= 0 && loop > 0) {
+ status = ei_receive_encoded(env->_fd, &env->_inbuf, &env->_inbufsz,
+ &msg, &env->_iin);
+ switch(status) {
+ case ERL_SEND:
+ case ERL_REG_SEND:
+ /* get result */
+ m_i__switch(NULL, env);
+ switch(env->_major) {
+ case CORBA_NO_EXCEPTION:
+ break;
+ case CORBA_SYSTEM_EXCEPTION:
+ fprintf(stderr, "Request failure, reason : %s\n",
+ (char *) CORBA_exception_value(env));
+ CORBA_exception_free(env);
+ break;
+ default: /* Should not happen */
+ CORBA_exception_free(env);
+ break;
+ }
+ /* send back result data */
+ if (env->_iout > 0)
+ ei_send_encoded(env->_fd, &env->_caller, env->_outbuf,
+ env->_iout);
+ loop = 0;
+ break;
+ case ERL_TICK:
+ break;
+ default:
+ if (status < 0) {
+ fprintf(stderr, "Status negative: %d\n", status);
+ loop = 0;
+ }
+ break;
+ }
+ }
+ my_gettimeofday(&stop);
+ showtime(&start, &stop);
+
+ erl_close_connection(fd);
+
+ CORBA_free(env->_inbuf);
+ CORBA_free(env->_outbuf);
+ CORBA_free(env);
+ if (status < 0)
+ done(-status);
+ else
+ done(0);
+}
+
+static void usage()
+{
+ fprintf(stderr, "Usage: %s [-help] -this-node-name <name> "
+ "-peer-node <nodename> -cookie <cookie>\n", progname);
+ fprintf(stderr, "Example:\n %s -this-node-name kalle "
+ "-peer-node olle@home -cookie oa678er\n", progname);
+}
+
+static void done(int r)
+{
+#ifdef __WIN32__
+ WSACleanup();
+#endif
+ exit(r);
+}
+
+static void showtime(MyTimeval *start, MyTimeval *stop)
+{
+ MyTimeval elapsed;
+
+ elapsed.tv_sec = stop->tv_sec - start->tv_sec;
+ elapsed.tv_usec = stop->tv_usec - start->tv_usec;
+ while (elapsed.tv_usec < 0) {
+ elapsed.tv_sec -= 1;
+ elapsed.tv_usec += 1000000;
+ }
+ fprintf(stderr,"%ld.%06ld seconds\n",elapsed.tv_sec, elapsed.tv_usec);
+}
+
+
+
+static void my_gettimeofday(MyTimeval *tv)
+#ifdef __WIN32__
+#define EPOCH_JULIAN_DIFF 11644473600i64
+{
+ SYSTEMTIME t;
+ FILETIME ft;
+ LONGLONG lft;
+
+ GetSystemTime(&t);
+ SystemTimeToFileTime(&t, &ft);
+ memcpy(&lft, &ft, sizeof(lft));
+ tv->tv_usec = (long) ((lft / 10i64) % 1000000i64);
+ tv->tv_sec = (long) ((lft / 10000000i64) - EPOCH_JULIAN_DIFF);
+}
+#elif defined VXWORKS
+{
+ int rate = sysClkRateGet(); /* Ticks per second */
+ unsigned long ctick = tickGet();
+ tv->tv_sec = ctick / rate; /* secs since reboot */
+ tv->tv_usec = ((ctick - (tv->tv_sec * rate))*1000000)/rate;
+}
+#else
+{
+ gettimeofday(tv, NULL);
+}
+#endif
diff --git a/lib/ic/test/erl_client_c_server_proto_SUITE_data/callbacks.c b/lib/ic/test/erl_client_c_server_proto_SUITE_data/callbacks.c
new file mode 100644
index 0000000000..b029bcc63c
--- /dev/null
+++ b/lib/ic/test/erl_client_c_server_proto_SUITE_data/callbacks.c
@@ -0,0 +1,610 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2004-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#ifndef __WIN32__
+# include <unistd.h>
+#endif
+#include <string.h>
+#include <ctype.h>
+#include <ic.h>
+#include <erl_interface.h>
+#include <ei.h>
+#include "m_i__s.h"
+
+
+
+/* OK */
+
+void my_void_test(CORBA_Object oe_obj,
+ CORBA_Environment *oe_env)
+{
+ /* printf("void test !\n"); */
+}
+
+m_i_void_test__rs* m_i_void_test__cb(CORBA_Object oe_obj,
+ CORBA_Environment *oe_env)
+{
+ return (m_i_void_test__rs*) (my_void_test);
+}
+
+
+
+/* OK */
+
+void my_long_test(CORBA_Object oe_obj,
+ long* a,
+ long* b,
+ long* c,
+ CORBA_Environment *oe_env)
+{
+ /* printf("long test !\n"); */
+}
+
+
+m_i_long_test__rs* m_i_long_test__cb(CORBA_Object oe_obj,
+ long* a,
+ long* b,
+ long* c,
+ CORBA_Environment *oe_env)
+{
+ *a = *b;
+ *c = *b;
+ return (m_i_long_test__rs*) (my_long_test);
+}
+
+/* OK */
+
+void my_longlong_test(CORBA_Object oe_obj,
+ CORBA_long_long* a,
+ CORBA_long_long* b,
+ CORBA_long_long* c,
+ CORBA_Environment *oe_env)
+{
+ /* printf("long test !\n"); */
+}
+
+m_i_longlong_test__rs* m_i_longlong_test__cb(CORBA_Object oe_obj,
+ CORBA_long_long* a,
+ CORBA_long_long* b,
+ CORBA_long_long* c,
+ CORBA_Environment *oe_env)
+{
+ *a = *b;
+ *c = *b;
+ return (m_i_longlong_test__rs*) (my_longlong_test);
+}
+
+/* OK */
+void my_ulong_test(CORBA_Object oe_obj,
+ unsigned long* a,
+ unsigned long* b,
+ unsigned long* c,
+ CORBA_Environment *oe_env)
+{
+ /* printf("ulong test !\n"); */
+}
+
+m_i_ulong_test__rs* m_i_ulong_test__cb(CORBA_Object oe_obj,
+ unsigned long* a,
+ unsigned long* b,
+ unsigned long* c,
+ CORBA_Environment *oe_env)
+{
+ *a = *b;
+ *c = *b;
+ return (m_i_ulong_test__rs*) (my_ulong_test);
+}
+
+/* OK */
+void my_ulonglong_test(CORBA_Object oe_obj,
+ CORBA_unsigned_long_long* a,
+ CORBA_unsigned_long_long* b,
+ CORBA_unsigned_long_long* c,
+ CORBA_Environment *oe_env)
+{
+ /* printf("ulong test !\n"); */
+}
+
+m_i_ulonglong_test__rs* m_i_ulonglong_test__cb(CORBA_Object oe_obj,
+ CORBA_unsigned_long_long* a,
+ CORBA_unsigned_long_long* b,
+ CORBA_unsigned_long_long* c,
+ CORBA_Environment *oe_env)
+{
+ *a = *b;
+ *c = *b;
+ return (m_i_ulonglong_test__rs*) (my_ulonglong_test);
+}
+
+m_i_ushort_test__rs* m_i_ushort_test__cb(CORBA_Object oe_obj,
+ unsigned short* a,
+ unsigned short* b,
+ unsigned short* c,
+ CORBA_Environment *oe_env)
+{
+ *a = *b;
+ *c = *b;
+ return (m_i_ushort_test__rs*) NULL;
+}
+
+
+/* OK */
+void my_double_test(CORBA_Object oe_obj,
+ double* a,
+ double* b,
+ double* c,
+ CORBA_Environment *oe_env)
+{
+ /* printf("double test !\n"); */
+}
+
+m_i_double_test__rs* m_i_double_test__cb(CORBA_Object oe_obj,
+ double* a,
+ double* b,
+ double* c,
+ CORBA_Environment *oe_env)
+{
+ *a = *b;
+ *c = *b;
+ return (m_i_double_test__rs*) (my_double_test);
+}
+
+/* OK */
+m_i_char_test__rs* m_i_char_test__cb(CORBA_Object oe_obj,
+ char* a,
+ char* b,
+ char* c,
+ CORBA_Environment *oe_env)
+{
+ m_i_char_test__rs* rs = NULL;
+
+ *a = *b;
+ *c = *b;
+ return rs;
+}
+
+
+/* OK */
+m_i_wchar_test__rs* m_i_wchar_test__cb(CORBA_Object oe_obj,
+ CORBA_wchar* a,
+ CORBA_wchar* b,
+ CORBA_wchar* c,
+ CORBA_Environment *oe_env)
+{
+ m_i_wchar_test__rs* rs = NULL;
+
+ *a = *b;
+ *c = *b;
+ return rs;
+}
+
+/* OK */
+m_i_octet_test__rs* m_i_octet_test__cb(CORBA_Object oe_obj,
+ char* a,
+ char* b,
+ char* c,
+ CORBA_Environment *oe_env)
+{
+ m_i_octet_test__rs* rs = NULL;
+
+ *a = *b;
+ *c = *b;
+ return rs;
+}
+
+/* OK */
+m_i_bool_test__rs* m_i_bool_test__cb(CORBA_Object oe_obj,
+ CORBA_boolean* a,
+ CORBA_boolean* b,
+ CORBA_boolean* c,
+ CORBA_Environment *oe_env)
+{
+ m_i_bool_test__rs* rs = NULL;
+
+ *a = *b;
+ *c = *b;
+ return rs;
+}
+
+/* OK */
+void my_struct_test(CORBA_Object oe_obj,
+ m_b* a,
+ m_b* b,
+ m_b* c,
+ CORBA_Environment *oe_env)
+{
+ /* printf("struct test !\n"); */
+}
+
+m_i_struct_test__rs* m_i_struct_test__cb(CORBA_Object oe_obj,
+ m_b* a,
+ m_b* b,
+ m_b* c,
+ CORBA_Environment *oe_env)
+{
+ *a = *b;
+ *c = *b;
+ return (m_i_struct_test__rs*) (my_struct_test);
+}
+
+/* OK */
+m_i_struct2_test__rs* m_i_struct2_test__cb(CORBA_Object oe_obj,
+ m_es* a,
+ m_es* b,
+ m_es* c,
+ CORBA_Environment *oe_env)
+{
+ m_i_struct2_test__rs* rs = NULL;
+
+ *a = *b;
+ *c = *b;
+ return rs;
+}
+
+/* OK */
+/* XXX Commented out
+m_i_struct3_test__rs* m_i_struct3_test__cb(CORBA_Object oe_obj,
+ m_simple* a,
+ m_simple* b,
+ m_simple* c,
+ CORBA_Environment *oe_env)
+{
+ m_i_struct3_test__rs* rs = NULL;
+ *a = *b;
+ *c = *b;
+ return rs;
+}
+*/
+
+/* OK */
+m_i_seq1_test__rs* m_i_seq1_test__cb(CORBA_Object oe_obj,
+ m_bseq** a,
+ m_bseq* b,
+ m_bseq** c,
+ CORBA_Environment *oe_env)
+{
+ m_i_seq1_test__rs* rs = NULL;
+
+ *a = b;
+ *c = b;
+ return rs;
+}
+
+
+/* OK */
+m_i_seq2_test__rs* m_i_seq2_test__cb(CORBA_Object oe_obj,
+ m_aseq** a,
+ m_aseq* b,
+ m_aseq** c,
+ CORBA_Environment *oe_env)
+{
+ m_i_seq2_test__rs* rs = NULL;
+
+ *a = b;
+ *c = b;
+ return rs;
+}
+
+/* OK */
+m_i_seq3_test__rs* m_i_seq3_test__cb(CORBA_Object oe_obj,
+ m_lseq** a,
+ m_lseq* b,
+ m_lseq** c,
+ CORBA_Environment *oe_env)
+{
+ m_i_seq3_test__rs* rs = NULL;
+
+ *a = b;
+ *c = b;
+ return rs;
+}
+
+/* OK */
+m_i_seq4_test__rs* m_i_seq4_test__cb(CORBA_Object oe_obj,
+ m_ssstr3** a,
+ m_ssstr3* b,
+ m_ssstr3** c,
+ CORBA_Environment *oe_env)
+{
+ m_i_seq4_test__rs* rs = NULL;
+
+ *a = b;
+ *c = b;
+ return rs;
+}
+
+/* OK */
+m_i_seq5_test__rs* m_i_seq5_test__cb(CORBA_Object oe_obj,
+ m_ssarr3** a,
+ m_ssarr3* b,
+ m_ssarr3** c,
+ CORBA_Environment *oe_env)
+{
+ m_i_seq5_test__rs* rs = NULL;
+
+ *a = b;
+ *c = b;
+ return rs;
+}
+
+/* OK */
+m_i_array1_test__rs* m_i_array1_test__cb(CORBA_Object oe_obj,
+ m_arr1 a,
+ m_arr1 b,
+ m_arr1 c,
+ CORBA_Environment *oe_env)
+{
+ int i;
+ m_i_array1_test__rs* rs = NULL;
+
+ for (i = 0; i < 500; i++) {
+ a[i] = b[i];
+ c[i] = b[i];
+ }
+ return rs;
+}
+
+/* OK */
+m_i_array2_test__rs* m_i_array2_test__cb(CORBA_Object oe_obj,
+ m_dd a,
+ m_dd b,
+ m_dd c,
+ CORBA_Environment *oe_env)
+{
+ int i,j;
+ m_i_array2_test__rs* rs = NULL;
+
+ for (i = 0; i < 2; i++)
+ for (j = 0; j < 3; j++) {
+ a[i][j] = b[i][j];
+ c[i][j] = b[i][j];
+ }
+ return rs;
+}
+
+
+/* OK */
+m_i_enum_test__rs* m_i_enum_test__cb(CORBA_Object oe_obj,
+ m_fruit* a,
+ m_fruit* b,
+ m_fruit* c,
+ CORBA_Environment *oe_env)
+{
+ m_i_enum_test__rs* rs = NULL;
+
+ *a = *b;
+ *c = *b;
+ return rs;
+}
+
+/* OK */
+m_i_string1_test__rs* m_i_string1_test__cb(CORBA_Object oe_obj,
+ char ** a,
+ char * b,
+ char ** c,
+ CORBA_Environment *oe_env)
+{
+ m_i_string1_test__rs* rs = NULL;
+
+ /*printf("\nString in ------> %s\n\n",b);*/
+ *a = b;
+ *c = b;
+ return rs;
+}
+
+/* OK */
+m_i_string2_test__rs* m_i_string2_test__cb(CORBA_Object oe_obj,
+ m_sseq** a,
+ m_sseq* b,
+ m_sseq** c,
+ CORBA_Environment *oe_env)
+{
+ m_i_string2_test__rs* rs = NULL;
+
+ *a = b;
+ *c = b;
+ return rs;
+}
+
+/* OK */
+m_i_string3_test__rs* m_i_string3_test__cb(CORBA_Object oe_obj,
+ char ** a,
+ char * b,
+ char ** c,
+ CORBA_Environment *oe_env)
+{
+ m_i_string3_test__rs* rs = NULL;
+
+ *a = b;
+ *c = b;
+ return rs;
+}
+
+m_i_string4_test__rs* m_i_string4_test__cb(CORBA_Object oe_obj,
+ m_strRec** a,
+ m_strRec* b,
+ m_strRec** c,
+ CORBA_Environment *oe_env)
+{
+ *a = b;
+ *c = b;
+
+ return (m_i_string4_test__rs*) NULL;
+}
+
+/* OK */
+m_i_wstring1_test__rs* m_i_wstring1_test__cb(CORBA_Object oe_obj,
+ CORBA_wchar ** a,
+ CORBA_wchar * b,
+ CORBA_wchar ** c,
+ CORBA_Environment *oe_env)
+{
+ int tmp;
+ m_i_wstring1_test__rs* rs = NULL;
+
+ /*printf("\nString in ------> %s\n\n",b);*/
+
+ for(tmp = 0; tmp < 5; tmp++)
+ fprintf(stderr,"\np[%d] = %ld\n", tmp, b[tmp]);
+ *a = b;
+ *c = b;
+ return rs;
+}
+
+
+/* OK */
+m_i_pid_test__rs* m_i_pid_test__cb(CORBA_Object oe_obj,
+ erlang_pid* a,
+ erlang_pid* b,
+ erlang_pid* c,
+ CORBA_Environment *oe_env)
+{
+ m_i_pid_test__rs* rs = NULL;
+
+ *a = *b;
+ *c = *b;
+ return rs;
+}
+
+/* OK */
+m_i_port_test__rs* m_i_port_test__cb(CORBA_Object oe_obj,
+ erlang_port* a,
+ erlang_port* b,
+ erlang_port* c,
+ CORBA_Environment *oe_env)
+{
+ m_i_port_test__rs* rs = NULL;
+
+ strcpy((*a).node,(*b).node);
+ (*a).id = (*b).id;
+ (*a).creation = 0;
+
+ strcpy((*c).node,(*b).node);
+ (*c).id = (*b).id;
+ (*c).creation = 0;
+ return rs;
+}
+
+/* OK */
+m_i_ref_test__rs* m_i_ref_test__cb(CORBA_Object oe_obj,
+ erlang_ref* a,
+ erlang_ref* b,
+ erlang_ref* c,
+ CORBA_Environment *oe_env)
+{
+
+ m_i_ref_test__rs* rs = NULL;
+
+ strcpy((*a).node,(*b).node);
+ /*(*a).id = (*b).id;*/
+ (*a).len = (*b).len;
+ (*a).n[0] = (*b).n[0];
+ (*a).n[1] = (*b).n[1];
+ (*a).n[2] = (*b).n[2];
+ (*a).creation = 0;
+
+ strcpy((*c).node,(*b).node);
+ /*(*c).id = (*b).id;*/
+ (*c).len = (*b).len;
+ (*c).n[0] = (*b).n[0];
+ (*c).n[1] = (*b).n[1];
+ (*c).n[2] = (*b).n[2];
+ (*c).creation = 0;
+ return rs;
+}
+
+/* OK */
+m_i_term_test__rs* m_i_term_test__cb(CORBA_Object oe_obj,
+ ETERM** a,
+ ETERM** b,
+ ETERM** c,
+ CORBA_Environment *oe_env)
+{
+ m_i_term_test__rs* rs = NULL;
+
+ *a = *b;
+ *c = *b;
+ return rs;
+}
+
+m_i_typedef_test__rs* m_i_typedef_test__cb(CORBA_Object oe_obj,
+ long* a,
+ ETERM** b,
+ erlang_port* c,
+ ETERM** d ,
+ erlang_port* e,
+ CORBA_Environment *oe_env)
+{
+ m_i_typedef_test__rs* rs = NULL;
+
+ *d = *b;
+ strcpy((*e).node,(*c).node);
+ (*e).id = (*c).id;
+ (*e).creation = 0;
+ *a = 4711;
+ return rs;
+}
+
+/* OK */
+m_i_inline_sequence_test__rs* m_i_inline_sequence_test__cb(
+ CORBA_Object oe_obj,
+ m_s** a,
+ m_s* b,
+ m_s** c,
+ CORBA_Environment *oe_env)
+{
+ m_i_inline_sequence_test__rs* rs = NULL;
+
+ *a = b;
+ *c = b;
+ return rs;
+}
+
+/* OK */
+m_i_term_sequence_test__rs* m_i_term_sequence_test__cb(
+ CORBA_Object oe_obj,
+ m_etseq** a,
+ m_etseq* b,
+ m_etseq** c,
+ CORBA_Environment *oe_env)
+{
+ m_i_term_sequence_test__rs* rs = NULL;
+
+ *a = b;
+ *c = b;
+ return rs;
+}
+
+
+/* OK */
+m_i_term_struct_test__rs* m_i_term_struct_test__cb(CORBA_Object oe_obj,
+ m_et* a,
+ m_et* b,
+ m_et* c,
+ CORBA_Environment *oe_env)
+{
+ m_i_term_struct_test__rs* rs = NULL;
+
+ *a = *b;
+ *c = *b;
+ return rs;
+}
+
diff --git a/lib/ic/test/erl_client_c_server_proto_SUITE_data/erl_c_test.idl b/lib/ic/test/erl_client_c_server_proto_SUITE_data/erl_c_test.idl
new file mode 100644
index 0000000000..e90d0dd5f0
--- /dev/null
+++ b/lib/ic/test/erl_client_c_server_proto_SUITE_data/erl_c_test.idl
@@ -0,0 +1,174 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 2004-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+#include "erlang.idl"
+
+
+const short TestConst = 1;
+
+module m {
+
+ const short TestConst = 2;
+
+ struct b {
+ long l;
+ char c;
+ };
+
+ struct simple {
+ long l;
+ b b_t;
+ };
+
+ enum fruit {orange, banana, apple, peach, pear};
+
+ typedef sequence<long> lseq;
+
+ typedef sequence<b> bseq;
+
+ struct a {
+ long l;
+ bseq y;
+ double d;
+ };
+
+ typedef sequence<a> aseq;
+
+ typedef sequence<string> sseq;
+ typedef string str;
+ typedef long myLong;
+
+ typedef long arr1[500], dd[2][3];
+
+ typedef erlang::term apa;
+ typedef erlang::port banan;
+
+ typedef sequence<erlang::term> etseq;
+
+ struct s {
+ long l;
+ sequence<long> sl;
+ };
+
+ struct es {
+ fruit f;
+ myLong l;
+ };
+
+ struct et {
+ erlang::term e;
+ long l;
+ };
+
+
+ typedef sequence<char> str1;
+ typedef string<12> str2;
+ typedef char str3[3];
+
+ typedef sequence<string> sstr3; // sequence of string
+ typedef sequence<sstr3> ssstr3; // sequence of sequences of strings
+
+ typedef long arr3[3]; // array of long
+ typedef sequence<arr3> sarr3; // sequence of array
+ typedef sequence<sarr3> ssarr3; // sequence of sequnces of arrays of strings
+
+ struct strRec{
+ boolean bb;
+ string str4;
+ long str7[3][2];
+ sequence<char> str5;
+ string<12> str6;
+ str3 str8;
+ str2 str9;
+ str1 str10;
+ };
+
+
+ struct dyn {
+ long l;
+ sequence<long> sl;
+ };
+ typedef dyn arr2[1][2];
+
+
+ interface i {
+
+ const short TestConst = 3;
+
+ //arr2 suck(in arr2 x, out arr2 y );
+
+ ///////////////////////////////// attribute long l;
+
+ // simple types
+ void void_test();
+ long long_test(in long a, out long a1);
+ long long longlong_test(in long long a, out long long a1);
+ unsigned short ushort_test(in unsigned short a, out unsigned short a1);
+ unsigned long ulong_test(in unsigned long a, out unsigned long a1);
+ unsigned long long ulonglong_test(in unsigned long long a, out unsigned long long a1);
+ double double_test(in double a, out double a1);
+ char char_test(in char a, out char a1);
+ wchar wchar_test(in wchar a, out wchar a1);
+ octet octet_test(in octet a, out octet a1);
+ boolean bool_test(in boolean a, out boolean a1);
+
+ // Seq. and struct tests
+ b struct_test(in b a, out b a1);
+ es struct2_test(in es a, out es a1);
+ //simple struct3_test(in simple x, out simple y);
+ bseq seq1_test(in bseq a, out bseq a1);
+ aseq seq2_test(in aseq a, out aseq a1);
+ lseq seq3_test(in lseq a, out lseq a1);
+ ssstr3 seq4_test(in ssstr3 a, out ssstr3 a1);
+ ssarr3 seq5_test(in ssarr3 a, out ssarr3 a1);
+
+ // Array tests
+ arr1 array1_test(in arr1 a, out arr1 a1);
+ dd array2_test(in dd a, out dd a1);
+
+ // enum test
+ fruit enum_test(in fruit a, out fruit a1);
+
+ // string tests
+ string string1_test(in string a, out string a1);
+ wstring wstring1_test(in wstring a, out wstring a1);
+ sseq string2_test(in sseq a, out sseq a1);
+ str string3_test(in str a, out str a1);
+ strRec string4_test(in strRec a, out strRec a1);
+
+ // Special erlang types
+ erlang::pid pid_test(in erlang::pid a, out erlang::pid a1);
+ erlang::port port_test(in erlang::port a, out erlang::port a1);
+ erlang::ref ref_test(in erlang::ref a, out erlang::ref a1);
+ erlang::term term_test(in erlang::term a, out erlang::term a1);
+
+ // typedef test
+ long typedef_test(in apa a, in banan b, out apa a1, out banan b1);
+
+ // inlined seq. test
+ s inline_sequence_test(in s a, out s a1);
+
+ // term seq. test
+ etseq term_sequence_test(in etseq a, out etseq a1);
+ // term struct test
+ et term_struct_test(in et a, out et a1);
+
+ };
+
+};
diff --git a/lib/ic/test/erl_client_c_server_proto_SUITE_data/erl_client.erl b/lib/ic/test/erl_client_c_server_proto_SUITE_data/erl_client.erl
new file mode 100644
index 0000000000..b5ee7af199
--- /dev/null
+++ b/lib/ic/test/erl_client_c_server_proto_SUITE_data/erl_client.erl
@@ -0,0 +1,331 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+-module(erl_client).
+
+-export([void_test/2, long_test/2, longlong_test/2, ushort_test/2,
+ ulong_test/2, ulonglong_test/2, double_test/2, char_test/2,
+ wchar_test/2, octet_test/2, bool_test/2, struct_test/2,
+ struct2_test/2, seq1_test/2, seq2_test/2, seq3_test/2,
+ seq4_test/2, seq5_test/2, array1_test/2, array2_test/2,
+ enum_test/2, string1_test/2, wstring1_test/2, string2_test/2,
+ string3_test/2, string4_test/2, pid_test/2, port_test/2,
+ ref_test/2, term_test/2, typedef_test/2,
+ inline_sequence_test/2, term_sequence_test/2,
+ term_struct_test/2
+
+]).
+
+-include("m.hrl").
+-include("m_i.hrl").
+-include("oe_erl_c_test.hrl").
+
+%%b
+void_test(Node, Timeout) ->
+ Ret = m_i:void_test({olsson, Node}, Timeout),
+ Ret == void. % XXX Not documented
+%%e
+
+%%b
+long_test(Node, Timeout) ->
+ In = max_long(),
+ {Ret, Out} = m_i:long_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+longlong_test(Node, Timeout) ->
+ In = 65537,
+ {Ret, Out} = m_i:longlong_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+ushort_test(Node, Timeout) ->
+ In = max_ushort(),
+ {Ret, Out} = m_i:ushort_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+ulong_test(Node, Timeout) ->
+ In = max_ulong(),
+ {Ret, Out} = m_i:ulong_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+ulonglong_test(Node, Timeout) ->
+ In = 65537,
+ {Ret, Out} = m_i:ulonglong_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+double_test(Node, Timeout) ->
+ In = 37768.93,
+ {Ret, Out} = m_i:double_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+char_test(Node, Timeout) ->
+ In = 80,
+ {Ret, Out} = m_i:char_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+wchar_test(Node, Timeout) ->
+ In = 4097,
+ {Ret, Out} = m_i:wchar_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+octet_test(Node, Timeout) ->
+ In = 255,
+ {Ret, Out} = m_i:octet_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+bool_test(Node, Timeout) ->
+ In = false,
+ {Ret, Out} = m_i:bool_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+struct_test(Node, Timeout) ->
+ In = #m_b{l = max_long(), c = $a},
+ {Ret, Out} = m_i:struct_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+struct2_test(Node, Timeout) ->
+ In = #m_es{ f = banana, l = max_long()},
+ {Ret, Out} = m_i:struct2_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+seq1_test(Node, Timeout) ->
+ B1 = #m_b{l = max_long(), c = $a},
+ B2 = #m_b{l = min_long(), c = $b},
+ In = [B1, B2],
+ {Ret, Out} = m_i:seq1_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+seq2_test(Node, Timeout) ->
+ B = #m_b{l = max_long(), c = $a},
+ A = #m_a{l = min_long(), y = [B, B], d = 4711.31},
+ In = [A, A, A],
+ {Ret, Out} = m_i:seq2_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+seq3_test(Node, Timeout) ->
+ In = [max_long(), min_long(), max_long()],
+ {Ret, Out} = m_i:seq3_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+seq4_test(Node, Timeout) ->
+ In = [["hej", "hopp"], ["ditt", "feta", "nylle"]],
+ {Ret, Out} = m_i:seq4_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+seq5_test(Node, Timeout) ->
+ Arr3 = mk_array(3, max_long()),
+ In = [[Arr3, Arr3], [Arr3, Arr3, Arr3]],
+ {Ret, Out} = m_i:seq5_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+array1_test(Node, Timeout) ->
+ In = mk_array(500, min_long()),
+ {Ret, Out} = m_i:array1_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+array2_test(Node, Timeout) ->
+ In = mk_array(2, mk_array(3, min_long())),
+ {Ret, Out} = m_i:array2_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+enum_test(Node, Timeout) ->
+ In = banana,
+ {Ret, Out} = m_i:enum_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+string1_test(Node, Timeout) ->
+ In = "Die Paula muss beim Tango immer weinen",
+ {Ret, Out} = m_i:string1_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+wstring1_test(Node, Timeout) ->
+ In = [1047| "ie Paula muss beim Tango immer weinen"],
+ {Ret, Out} = m_i:wstring1_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+string2_test(Node, Timeout) ->
+ In = ["Lass doch die Blumen,", "Konrad!"],
+ {Ret, Out} = m_i:string2_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+string3_test(Node, Timeout) ->
+ In = "Seeman, lass uns freuden!",
+ {Ret, Out} = m_i:string3_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+string4_test(Node, Timeout) ->
+
+ In = #m_strRec{
+ bb = true,
+ str4 = "Paula war zu Hause in ihrem Stadtchen als die beste Tanzerin"
+ "bekannt",
+ str7 = mk_array(3, mk_array(2, max_long())),
+ str5 = [$a, $b, $c, $d, $e, $f],
+ str6 = "123456789012",
+ str8 = {$x, $y, $x},
+ str9 = "123456789012",
+ str10 = [$a, $b, $c, $d, $e, $f]
+ },
+ {Ret, Out} = m_i:string4_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+pid_test(Node, Timeout) ->
+ In = self(),
+ {Ret, Out} = m_i:pid_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+port_test(Node, Timeout) ->
+ In = get(port_test_port),
+ {Ret, Out} = m_i:port_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+ref_test(Node, Timeout) ->
+ In = make_ref(),
+ {Ret, Out} = m_i:ref_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+term_test(Node, Timeout) ->
+ In = {[a, b], 17, kalle},
+ {Ret, Out} = m_i:term_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+typedef_test(Node, Timeout) ->
+ In1 = {nisse, [1, 2], olsson},
+ In2 = get(port_test_port),
+ {Ret, Out1, Out2} = m_i:typedef_test({olsson, Node}, Timeout, In1, In2),
+ %% XXX Should check that Ret is an integer.
+ (Out1 == In1) and (Out2 == In2).
+%%e
+
+%%b
+inline_sequence_test(Node, Timeout) ->
+ In = #m_s{l = min_long(), sl = [max_long(), min_long()]},
+ {Ret, Out} = m_i:inline_sequence_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+term_sequence_test(Node, Timeout) ->
+ In = lists:duplicate(17, {nisse, [1, 2], {kalle, olsson}}),
+ {Ret, Out} = m_i:term_sequence_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+%%b
+term_struct_test(Node, Timeout) ->
+ In = #m_et{e = {nisse, ["abcde"], {kalle, olsson}}, l = 4711},
+ {Ret, Out} = m_i:term_struct_test({olsson, Node}, Timeout, In),
+ (Ret == In) and (Out == In).
+%%e
+
+
+%% Locals
+
+mk_array(Es) ->
+ list_to_tuple(Es).
+
+mk_array(N, E) ->
+ mk_array(lists:duplicate(N, E)).
+
+%% max_short() ->
+%% power_of_two(15) - 1.
+max_long() ->
+ power_of_two(31) - 1.
+max_longlong() ->
+ power_of_two(63) - 1.
+max_ushort() ->
+ power_of_two(16) - 1.
+max_ulong() ->
+ power_of_two(32) - 1.
+max_ulonglong() ->
+ power_of_two(64) - 1.
+
+%% min_short() ->
+%% -power_of_two(15).
+min_long() ->
+ -power_of_two(31).
+%% min_longlong() ->
+%% -power_of_two(63).
+%% min_ushort() ->
+%% 0.
+%% min_ulong() ->
+%% 0.
+%% min_ulonglong() ->
+%% 0.
+
+power_of_two(N) ->
+ round(math:pow(2, N)).
+
diff --git a/lib/ic/test/erl_client_c_server_proto_SUITE_data/my.c b/lib/ic/test/erl_client_c_server_proto_SUITE_data/my.c
new file mode 100644
index 0000000000..c0401b2621
--- /dev/null
+++ b/lib/ic/test/erl_client_c_server_proto_SUITE_data/my.c
@@ -0,0 +1,34 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2004-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+ */
+#include "ic.h"
+#include "m_i.h"
+
+int my_prepare_request_decoding(CORBA_Environment *env)
+{
+ return oe_prepare_request_decoding(env);
+}
+
+int my_prepare_reply_encoding(CORBA_Environment *env)
+{
+ return oe_prepare_reply_encoding(env);
+}
+
+
+
diff --git a/lib/ic/test/ic.spec b/lib/ic/test/ic.spec
new file mode 100644
index 0000000000..280c2aba47
--- /dev/null
+++ b/lib/ic/test/ic.spec
@@ -0,0 +1 @@
+{topcase, {dir, "../ic_test"}}.
diff --git a/lib/ic/test/ic.spec.vxworks b/lib/ic/test/ic.spec.vxworks
new file mode 100644
index 0000000000..b15260ab70
--- /dev/null
+++ b/lib/ic/test/ic.spec.vxworks
@@ -0,0 +1,2 @@
+{topcase, {dir, "../ic_test"}}.
+{skip,{ic_pp_SUITE,"Uses gcc"}}.
diff --git a/lib/ic/test/ic_SUITE.erl b/lib/ic/test/ic_SUITE.erl
new file mode 100644
index 0000000000..6682c82f01
--- /dev/null
+++ b/lib/ic/test/ic_SUITE.erl
@@ -0,0 +1,973 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+%%%----------------------------------------------------------------------
+%%% Purpose : Test suite for the IDL compiler
+%%%----------------------------------------------------------------------
+
+-module(ic_SUITE).
+-include("test_server.hrl").
+
+-export([all/1]).
+
+
+-include_lib("orber/src/orber_ifr.hrl").
+-include_lib("orber/src/ifr_objects.hrl").
+-include_lib("orber/include/ifr_types.hrl").
+
+
+%% The type cases
+-export([type/1, type_norm/1]).
+
+%% The syntax case
+-export([syntax/1]).
+-export([syntax1/1, syntax2/1, syntax3/1, syntax4/1, syntax5/1, syntax6/1]).
+
+%% The constant cases
+-export([const/1]).
+-export([const_norm/1, const_bad_tk/1, const_bad_type/1]).
+-export([const_bad_comb/1]).
+
+%% The union cases
+-export([union/1]).
+-export([union_norm/1, union_type/1, union_mult_err/1, union_case_mult/1]).
+-export([union_default/1]).
+
+%% The enum cases
+-export([enum/1]).
+-export([enum_norm/1]).
+
+%% The struct cases
+-export([struct/1]).
+-export([struct_norm/1]).
+
+%% The oneway cases
+-export([oneway/1]).
+-export([oneway_norm/1, oneway_raises/1, oneway_out/1, oneway_void/1, oneway_followed/1]).
+
+%% The attributes cases
+-export([attr/1]).
+-export([attr_norm/1]).
+
+%% The raises registration case
+-export([raises_reg/1]).
+
+
+%% The typeID case
+
+%% general stuff
+-export([general/1]).
+-export([typeid/1, undef_id/1, dir/1, nasty_names/1, coss/1, mult_ids/1]).
+-export([forward/1, include/1, app_test/1]).
+
+%% inheritance stuff
+-export([inherit/1, inherit_norm/1, inherit_warn/1, inherit_err/1]).
+
+%% Standard options to the ic compiler, NOTE unholy use of OutDir
+
+-define(OUT(X), filename:join([?config(priv_dir, Config), gen, to_list(X)])).
+
+
+%% Top of cases
+
+all(doc) ->
+ [];
+all(suite) -> [app_test, const, union, enum, attr, type, struct, general, inherit,
+ oneway, syntax, raises_reg].
+
+
+app_test(doc) -> [];
+app_test(suite) -> [];
+app_test(_Config) ->
+ ok=test_server:app_test(ic),
+ ok.
+
+%%---------------------------------------------------------------------
+%%
+%% Test of constant expressions.
+%%
+
+const(suite) -> [const_norm, const_bad_tk, const_bad_type, const_bad_comb].
+
+
+const_norm(doc) ->
+ ["Checks normal constant types and values"];
+const_norm(suite) -> [];
+const_norm(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(const_norm),
+ File = filename:join(DataDir, c_norm),
+ ?line ok = ic:gen(File, stdopts(OutDir)),
+ ?line {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]),
+ ?line ok = compile(OutDir, const_norm_files()),
+ ok.
+
+const_bad_tk(doc) ->
+ ["Checks when the constant value doesn't match the declared type"];
+const_bad_tk(suite) -> [];
+const_bad_tk(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(slask),
+ File = filename:join(DataDir, c_err1),
+ ?line error = ic:gen(File, stdopts(OutDir)),
+ ?line {error, [], R} =
+ ic:gen(File, stdopts(OutDir)++[silent2]),
+ check_errors(18, bad_tk_match, R),
+ ok.
+
+const_bad_type(doc) ->
+ ["Checks operands of ops are of correct type"];
+const_bad_type(suite) -> [];
+const_bad_type(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(slask),
+ File = filename:join(DataDir, c_err2),
+ ?line error = ic:gen(File, stdopts(OutDir)),
+ ?line {error, [], R} =
+ ic:gen(File, stdopts(OutDir)++[silent2]),
+ check_errors(4, bad_type, R),
+ ok.
+
+const_bad_comb(doc) ->
+ ["Checks operands of ops are of conflicting types"];
+const_bad_comb(suite) -> [];
+const_bad_comb(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(slask),
+ File = filename:join(DataDir, c_err3),
+ ?line error = ic:gen(File, stdopts(OutDir)),
+ ?line {error, [], R} =
+ ic:gen(File, stdopts(OutDir)++[silent2]),
+ check_errors(3, bad_type_combination, R),
+ ok.
+
+
+
+union(suite) -> [union_norm, union_type, union_mult_err, union_case_mult,
+ union_default];
+union(doc) ->
+ ["Checks allowed usage of the union as well as the illegal cases"].
+
+
+union_norm(doc) ->
+ ["Checks that normal union declarations works."];
+union_norm(suite) -> [];
+union_norm(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(union_norm),
+ File = filename:join(DataDir, u_norm),
+
+ ?line ok = ic:gen(File, stdopts(OutDir)),
+ ?line {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]),
+ ?line ok = compile(OutDir, union_norm_files()),
+ ok.
+
+
+%% Checks OTP-2007
+union_default(doc) ->
+ ["Checks that default cases are correct in type code."];
+union_default(suite) -> [];
+union_default(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(union_default),
+ File = filename:join(DataDir, u_default),
+
+ ?line ok = ic:gen(File, stdopts(OutDir)),
+ ?line {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]),
+ ?line ok = compile(OutDir, union_default_files(), [load]),
+ TkList = i1:oe_get_interface(),
+ check_label("op0", 0, TkList),
+ check_label("op1", 1, TkList),
+ check_label("op2", 2, TkList),
+ check_label("op3", -1, TkList),
+ ok.
+
+check_label(Id, N, List) ->
+ case lists:keysearch(Id, 1, List) of
+ {value, {_, {{_, _, _, _, D, L}, _, _}}} ->
+ if D /= N ->
+ test_server:fail({bad_default_num, D, N});
+ D /= -1 ->
+ case lists:nth(D+1, L) of
+ T when element(1, T) == default ->
+ ok;
+ _Que ->
+ test_server:fail({bad_default_list, D, L})
+ end;
+ true ->
+ %% D = N = -1, just check that there is no default label
+ case lists:keysearch(default, 1, L) of
+ false ->
+ ok;
+ _ ->
+ test_server:fail({bad_default_label, D, L})
+ end
+ end;
+ _ ->
+ test_server:fail({'no_such_op!', Id, List})
+ end.
+
+union_type(doc) ->
+ ["Checks that errors are detected. Check that mismatch between case ",
+ "value and declared discriminator type is detected."];
+union_type(suite) -> [];
+union_type(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(slask),
+ File = filename:join(DataDir, u_type),
+ ?line error = ic:gen(File, stdopts(OutDir)),
+ ?line {error, [], R} =
+ ic:gen(File, stdopts(OutDir)++[silent2]),
+ check_errors(28, bad_case_type, R),
+ ok.
+
+
+union_mult_err(doc) ->
+ ["Check that multiple declared declarators are caught.",
+ "Also check that if the discriminator is an enum, then the enum name",
+ "must not be used as a declarator in the union switch (declarator",
+ "as opposed to label)."];
+union_mult_err(suite) -> [];
+union_mult_err(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(slask),
+ File = filename:join(DataDir, u_mult),
+ ?line error = ic:gen(File, stdopts(OutDir)),
+ ?line {error, [], R} =
+ ic:gen(File, stdopts(OutDir)++[silent2]),
+ check_errors(8, multiply_defined, R),
+ ok.
+
+%% Checking mult cases. Now check that other errors are found in the
+%% correct order XXXX
+
+
+union_case_mult(doc) ->
+ ["Check that multiply defined case labels are found and reported."];
+union_case_mult(suite) -> [];
+union_case_mult(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(slask),
+ File = filename:join(DataDir, u_case_mult),
+ ?line error = ic:gen(File, stdopts(OutDir)),
+ ?line {error, [], R} =
+ ic:gen(File, stdopts(OutDir)++[silent2]),
+ check_errors(7, multiple_cases, R),
+ ok.
+
+
+%%--------------------------------------------------------------------
+%%
+%% Enum cases
+%%
+
+enum(suite) -> [enum_norm];
+enum(doc) ->
+ ["Checks allowed usage of the enum as well as the illegal cases"].
+
+enum_norm(doc) ->
+ ["Checks that normal enum declarations works."];
+enum_norm(suite) -> [];
+enum_norm(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(enum_norm),
+ File = filename:join(DataDir, enum),
+
+ ?line ok = ic:gen(File, stdopts(OutDir)),
+ ?line {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]),
+ ?line ok = compile(OutDir, enum_norm_files()),
+ ok.
+
+
+%%--------------------------------------------------------------------
+%%
+%% Struct cases
+%%
+
+struct(suite) -> [struct_norm];
+struct(doc) ->
+ ["Checks allowed usage of the struct as well as the illegal cases"].
+
+struct_norm(doc) ->
+ ["Checks that normal struct declarations works."];
+struct_norm(suite) -> [];
+struct_norm(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(struct_norm),
+ File = filename:join(DataDir, struct),
+
+ ?line ok = ic:gen(File, stdopts(OutDir)),
+ ?line {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]),
+ ?line ok = compile(OutDir, struct_norm_files()),
+ Mod = ridiculous_name_to_avoid_clash_svenne,
+ TestFile = filename:join(OutDir, Mod),
+ ?line ok = gen_struct_file(TestFile, Mod),
+ ?line ok = compile(OutDir, [Mod], [load]),
+%% ?line {ok, Mod, []} = compile:file(TestFile,
+%% [{i, OutDir}, {outdir, OutDir},
+%% return, load]),
+ ?line ok = Mod:test(),
+ ok.
+
+
+%%--------------------------------------------------------------------
+%%
+%% General cases
+%%
+
+general(doc) ->
+ ["Check general things like directories and type identifier",
+ "detection."];
+general(suite) -> [typeid, undef_id, mult_ids, forward, include, nasty_names].
+%% coss (add sometimes, takes 440 seconds!)
+
+typeid(doc) ->
+ ["Check that type id's are generated correctly"];
+typeid(suite) -> [];
+typeid(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(typeid),
+ File = filename:join(DataDir, typeid),
+
+ ?line ok = ic:gen(File, stdopts(OutDir)),
+ ?line {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]),
+ ?line ok = compile(OutDir, typeid_files(), [load]),
+ ?line "IDL:I1:1.0" = 'I1':'typeID'(),
+ ?line "IDL:M1/I1:1.0" = 'M1_I1':'typeID'(),
+ ?line "IDL:M2/M1/I1:1.0" = 'M2_M1_I1':'typeID'(),
+ ?line "IDL:M3/M2/M1/I1:1.0" = 'M3_M2_M1_I1':'typeID'(),
+ ok.
+
+
+%%% This test case is removed because there's no way to test this from
+%%% an automated test suite.
+dir(doc) ->
+ ["Check that relative directories work, absolute is used in",
+ "all other cases in the suite."];
+%%% xxxxxx
+dir(suite) -> [];
+dir(Config) when is_list(Config) ->
+ok;
+dir(Config) ->
+ DataDir = ?config(data_dir, Config),
+
+ %% Needs a unique directory (any better way?)
+ OutDir = mk_unique("oe_the_dir"),
+
+ %% More unique names
+ File = filename:join(DataDir, mk_unique("oe_the_file")),
+ Const = mk_unique("oe_the_constant"),
+ Mod = list_to_atom(File),
+ Func = list_to_atom(Const),
+
+ %% Generate a unique IDL file with a single constant
+ gen_file(File, Const),
+
+ ?line ok = ic:gen(File, stdopts(OutDir)),
+ ?line ok = compile(OutDir, [load]),
+ ?line 19955 = Mod:Func(),
+ ?line {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]),
+ ?line ok = compile(OutDir, [load]),
+ ?line 19955 = Mod:Func(),
+
+ ?line ok = ic:gen(File),
+%%% ?line ok = compile(".", [load]),
+ ok.
+
+undef_id(doc) ->
+ ["Check that various undefied id's are detected correctly"];
+undef_id(suite) -> [];
+undef_id(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(slask),
+ File = filename:join(DataDir, undef_id),
+ ?line error = ic:gen(File, stdopts(OutDir)),
+ ?line {error, [], R} =
+ ic:gen(File, stdopts(OutDir)++[silent2]),
+ check_errors(16, tk_not_found, R),
+ ok.
+
+mult_ids(doc) ->
+ ["Check that multiply defined ids are caught."];
+mult_ids(suite) -> [];
+mult_ids(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(slask),
+ File = filename:join(DataDir, mult_ids),
+ ?line error = ic:gen(File, stdopts(OutDir)),
+ ?line {error, [], R} =
+ ic:gen(File, stdopts(OutDir)++[silent2]),
+ check_errors(22, multiply_defined, R),
+ ok.
+
+
+nasty_names(doc) ->
+ ["Check that various nasty names can be generated.",
+ "Try to provoke name clashes and name conflicts with",
+ "Erlang and IDL"];
+nasty_names(suite) -> [];
+nasty_names(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(nasty_names),
+ File = filename:join(DataDir, nasty),
+
+ ?line ok = ic:gen(File, stdopts(OutDir)),
+ ?line {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]),
+ ?line ok = compile(OutDir, nasty_names_files(), [load]),
+ ok.
+
+coss(doc) ->
+ ["Check that the Coss standard specification works."];
+coss(suite) -> [];
+coss(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(coss),
+ File = filename:join(DataDir, 'Coss'),
+
+ ?line ok = ic:gen(File, stdopts(OutDir)),
+ ?line {ok, [_W1]} = ic:gen(File, stdopts(OutDir)++[silent2]),
+ ?line ok = compile(OutDir, []),
+ ok.
+
+forward(doc) ->
+ ["Check that forward declaratios work."];
+forward(suite) -> [];
+forward(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(forward),
+ File = filename:join(DataDir, forward),
+
+ ?line ok = ic:gen(File, stdopts(OutDir)),
+ ?line {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]),
+ ?line ok = compile(OutDir, forward_files(), [load]),
+ ok.
+
+include(doc) ->
+ ["Check that various undefied id's are detected correctly"];
+include(suite) -> [];
+include(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(slask),
+ File = filename:join(DataDir, include),
+ ?line error = ic:gen(File, stdopts(OutDir)++[{preproc_flags,"-I" ++ DataDir}]),
+ ?line {error, [], R} =
+ ic:gen(File, stdopts(OutDir)++[{preproc_flags,"-I" ++ DataDir},silent2]),
+ case lists:map(fun(D) ->
+ filename:rootname(filename:basename(element(3, D)))
+ end,
+ lists:sort(R)) of
+ ["include",
+ "include2",
+ "include2",
+ "include3"] ->
+ ok;
+ RRR ->
+ test_server:fail({bad_include_file, RRR})
+ end,
+ ok.
+
+
+
+
+%%--------------------------------------------------------------------
+%%
+%% Inhertit cases
+%%
+
+inherit(doc) ->
+ ["Check the inheritance mechanism."];
+inherit(suite) -> [inherit_norm, inherit_warn, inherit_err].
+
+inherit_norm(doc) ->
+ ["Checks that normal inheritance works."];
+inherit_norm(suite) -> [];
+inherit_norm(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(inherit_norm),
+ File = filename:join(DataDir, inherit),
+
+ ?line ok = ic:gen(File, stdopts(OutDir)),
+ ?line {ok, _Ws} = ic:gen(File, stdopts(OutDir)++[silent2]),
+ ?line ok = compile(OutDir, inherit_norm_files(), [load]),
+
+ %% Now check constant values:
+ ?line 9 = m1_I1:c1(),
+
+ ?line 9 = m1_I2:c1(),
+ ?line 14 = m1_I2:c2(),
+ ?line 27 = m1_I2:c3(),
+
+ ?line 50 = m1_I3:c1(),
+ ?line 14 = m1_I3:c2(),
+ ?line 27 = m1_I3:c3(),
+ ?line 91 = m1_I3:c4(),
+ ?line 100 = m1_I3:c5(),
+ ok.
+
+inherit_warn(doc) ->
+ ["Check that various inheritance shadowing is detected"];
+inherit_warn(suite) -> [];
+inherit_warn(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(slask),
+ File = filename:join(DataDir, inherit_warn),
+ ?line ok = ic:gen(File, stdopts(OutDir)),
+ ?line {ok, R} =
+ ic:gen(File, stdopts(OutDir)++[silent2]),
+ check_errors(7, inherit_name_shadow, R),
+ ok.
+
+inherit_err(doc) ->
+ ["Check that various inheritance errors is detected"];
+inherit_err(suite) -> [];
+inherit_err(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(slask),
+ File = filename:join(DataDir, inherit_err),
+ ?line error = ic:gen(File, stdopts(OutDir)),
+ ?line {error, _Ws, R} =
+ ic:gen(File, stdopts(OutDir)++[silent2]),
+ check_errors(21, inherit_name_collision, R),
+ ok.
+
+
+oneway(doc) ->
+ ["Check the oneway operation mechanism."];
+oneway(suite) -> [oneway_norm, oneway_out, oneway_raises, oneway_void, oneway_followed ].
+
+oneway_norm(doc) ->
+ ["Checks that normal oneway operations works."];
+oneway_norm(suite) -> [];
+oneway_norm(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(oneway_norm),
+ File = filename:join(DataDir, one),
+
+ ?line ok = ic:gen(File, stdopts(OutDir)),
+ ?line ok = compile(OutDir, oneway_norm_files(), [load]),
+ ?line {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]),
+ ?line ok = compile(OutDir, oneway_norm_files(), [load]),
+ ok.
+
+oneway_void(doc) ->
+ ["Check that non-void oneways are detected."];
+oneway_void(suite) -> [];
+oneway_void(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(slask),
+ File = filename:join(DataDir, one_void),
+ ?line error = ic:gen(File, stdopts(OutDir)),
+ ?line {error, [], R} =
+ ic:gen(File, stdopts(OutDir)++[silent2]),
+ check_errors(2, bad_oneway_type, R),
+ ok.
+
+oneway_raises(doc) ->
+ ["Check that oneways cannot raise exceptions."];
+oneway_raises(suite) -> [];
+oneway_raises(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(slask),
+ File = filename:join(DataDir, one_raises),
+ ?line error = ic:gen(File, stdopts(OutDir)),
+ ?line {error, [], R} =
+ ic:gen(File, stdopts(OutDir)++[silent2]),
+ check_errors(3, oneway_raises, R),
+ ok.
+
+oneway_out(doc) ->
+ ["Check that illegal out parameters are detected"];
+oneway_out(suite) -> [];
+oneway_out(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(slask),
+ File = filename:join(DataDir, one_out),
+ ?line error = ic:gen(File, stdopts(OutDir)),
+ ?line {error, [], R} =
+ ic:gen(File, stdopts(OutDir)++[silent2]),
+ check_errors(2, oneway_outparams, R),
+ ok.
+
+oneway_followed(doc) ->
+ ["Checks that normal oneways, followed by other operations."];
+oneway_followed(suite) -> [];
+oneway_followed(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(oneway_followed),
+ File = filename:join(DataDir, one_followed),
+
+ ?line ok = ic:gen(File, stdopts(OutDir)),
+ ?line ok = compile(OutDir, oneway_followed_files(), [load]),
+ ?line {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]),
+ ?line ok = compile(OutDir, oneway_followed_files(), [load]),
+ ok.
+
+attr(doc) ->
+ ["Check that attributes work."];
+attr(suite) -> [attr_norm].
+
+attr_norm(doc) ->
+ ["Checks that normal attr operations works."];
+attr_norm(suite) -> [];
+attr_norm(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(attr_norm),
+ File = filename:join(DataDir, attr),
+
+ ?line ok = ic:gen(File, stdopts(OutDir)),
+ ?line ok = compile(OutDir, attr_norm_files(), [load]),
+ ?line {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]),
+ ?line ok = compile(OutDir, attr_norm_files(), [load]),
+ ok.
+
+type(doc) ->
+ ["Check that typeibutes work."];
+type(suite) -> [type_norm].
+
+type_norm(doc) ->
+ ["Checks all types are handled."];
+type_norm(suite) -> [];
+type_norm(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(type_norm),
+ File = filename:join(DataDir, type),
+
+ ?line ok = ic:gen(File, stdopts(OutDir)),
+ ?line ok = compile(OutDir, type_norm_files(), [load]),
+ ?line {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]),
+ ?line ok = compile(OutDir, type_norm_files(), [load]),
+ ok.
+
+
+syntax(doc) ->
+ ["Check that syntax errors are discovered."];
+syntax(suite) -> [syntax1, syntax2, syntax3, syntax4, syntax5, syntax6].
+
+syntax1(suite) -> [];
+syntax1(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(slask),
+ File = filename:join(DataDir, syntax1),
+
+ ?line error = ic:gen(File, stdopts(OutDir)),
+ ?line {error, [], R} =
+ ic:gen(File, stdopts(OutDir)++[silent2]),
+ check_errors(1, parse_error, R),
+ ok.
+
+syntax2(suite) -> [];
+syntax2(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(slask),
+ File = filename:join(DataDir, syntax2),
+
+ ?line error = ic:gen(File, stdopts(OutDir)),
+ ?line {error, [], R} =
+ ic:gen(File, stdopts(OutDir)++[silent2]),
+ check_errors(1, parse_error, R),
+ ok.
+
+syntax3(suite) -> [];
+syntax3(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(slask),
+ File = filename:join(DataDir, syntax3),
+
+ ?line error = ic:gen(File, stdopts(OutDir)),
+ ?line {error, [], R} =
+ ic:gen(File, stdopts(OutDir)++[silent2]),
+ check_errors(1, parse_error, R),
+ ok.
+
+syntax4(suite) -> [];
+syntax4(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(slask),
+ File = filename:join(DataDir, syntax4),
+
+ ?line error = ic:gen(File, stdopts(OutDir)),
+ ?line {error, [], R} =
+ ic:gen(File, stdopts(OutDir)++[silent2]),
+ check_errors(1, parse_error, R),
+ ok.
+
+syntax5(suite) -> [];
+syntax5(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(slask),
+ File = filename:join(DataDir, syntax5),
+
+ ?line error = ic:gen(File, stdopts(OutDir)),
+ ?line {error, [], R} =
+ ic:gen(File, stdopts(OutDir)++[silent2]),
+ check_errors(1, parse_error, R),
+ ok.
+
+syntax6(suite) -> [];
+syntax6(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(slask),
+ File = filename:join(DataDir, syntax6),
+
+ ?line error = ic:gen(File, stdopts(OutDir)),
+ ?line {error, [], R} =
+ ic:gen(File, stdopts(OutDir)++[silent2]),
+ check_errors(1, parse_error, R),
+ ok.
+
+
+
+%%--------------------------------------------------------------------
+%%
+%% Checks RAISES to be registered under IFR operation registration
+%% ( OTP-2102 )
+%%
+
+raises_reg(doc) ->
+ ["Check that exceptions are really registered to operations."];
+raises_reg(suite) -> [];
+raises_reg(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(raises_reg_check),
+ File = filename:join(DataDir, raises_reg),
+
+ ?line ok = ic:gen(File, stdopts(OutDir)),
+ ?line {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]),
+ ?line ok = compile(OutDir, raises_reg_files(), [load]),
+
+ set_up('oe_raises_reg'),
+
+ io:format("~n##### Starting the test case #####~n"),
+ io:format("Checking for existance of exception : ~s~n",["IDL:Raises_RegModule/Exception_1:1.0"]),
+ raises_register_check("IDL:Raises_RegModule/R_R/op:1.0","IDL:Raises_RegModule/Exception_1:1.0"),
+
+ io:format("Checking for existance of exception : ~s~n",["IDL:Raises_RegModule/Exception_2:1.0"]),
+ raises_register_check("IDL:Raises_RegModule/R_R/op:1.0","IDL:Raises_RegModule/Exception_2:1.0"),
+
+ io:format("Checking for existance of exception : ~s~n",["IDL:Raises_RegModule/XXXXXXXX:1.0"]),
+ raises_register_check("IDL:Raises_RegModule/R_R/op:1.0","IDL:RaisesModule/XXXXXXXX:1.0"),
+
+ set_down('oe_raises_reg'),
+
+ ok.
+
+set_up(Register) ->
+ io:format("Setting up.....~n"),
+ mnesia:stop(),
+ mnesia:delete_schema([node()]),
+ mnesia:create_schema([node()]),
+ mnesia:start(),
+ orber:install([node()]),
+ orber:start(),
+ io:format("Running OE_register()~n"),
+ Register:'oe_register'().
+
+set_down(Register) ->
+ io:format("Running OE_unregister()~n"),
+ Register:'oe_unregister'(),
+ io:format("Setting down.....~n"),
+ orber:stop(),
+ orber:uninstall(),
+ mnesia:stop(),
+ mnesia:delete_schema([node()]).
+
+
+raises_register_check(OpId,ExcId) ->
+ case is_valid_exc(OpId,ExcId) of
+ true ->
+ ok; % Because right exception where found,
+ % the test succeeds for normal cases.
+ false ->
+ ok; % Because the exception tested, is not
+ % registered for that operation.
+ FailReason ->
+ test_server:fail({FailReason, OpId, ExcId})
+ % Because the test descovered errors in a previous
+ % stage, or no exceptions where registered att all.
+ % ( This testcase assumes that operations to be
+ % checked allways raise excption(s) )
+ end.
+
+is_valid_exc(OpId,ExcId) ->
+ OE_IFR = orber_ifr:find_repository(),
+ OpDef = orber_ifr:'Repository_lookup_id'(OE_IFR,OpId),
+ ExcDefList = orber_ifr:get_exceptions(OpDef),
+ case ExcDefList of
+ [] ->
+ no_exceptions_registered;
+ _ ->
+ ExcDef=orber_ifr:lookup_id(OE_IFR,ExcId),
+ lists:member(ExcDef,ExcDefList)
+ end.
+
+%%--------------------------------------------------------------------
+%%
+%% Utilities
+
+
+stdopts(OutDir) ->
+ [{outdir, OutDir},{maxerrs, infinity}].
+
+mk_unique(Prefix) ->
+ {A,B,C} = now(),
+ Prefix++"_"++integer_to_list(A)++"_"++integer_to_list(B)++"_"++
+ integer_to_list(C).
+
+gen_file(File, Const) ->
+ {ok, Fd} = file:open(File++".idl", [write]),
+ io:format(Fd, "interface ~s {~n", [File]),
+ io:format(Fd, " const long ~s = 19955;~n", [Const]),
+ io:format(Fd, "};~n", []),
+ file:close(Fd).
+
+
+%% Compile all files in Dir. Used for checking that valid Erlang has
+%% been generated.
+%%compile(Dir) ->
+%% compile(Dir, []).
+%%compile(Dir, Opts) ->
+%% {ok, Cwd} = file:get_cwd(),
+%% catch do_compile(Dir, Opts),
+%% file:set_cwd(Cwd).
+
+%%do_compile(Dir, Opts) ->
+%% ok = file:set_cwd(Dir),
+%% up_to_date = ts_make_erl:all(Opts),
+%% ok.
+
+compile(Dir, Files) ->
+ compile(Dir, Files, []).
+
+compile(Dir, Files, Opts) ->
+ {ok, Cwd} = file:get_cwd(),
+ file:set_cwd(Dir),
+ io:format("Changing to ~p~n", [Dir]),
+ case catch do_compile(Files, Opts) of
+ ok ->
+ file:set_cwd(Cwd);
+ Err ->
+ file:set_cwd(Cwd),
+ test_server:fail(Err)
+ end.
+
+do_compile([], _Opts) -> ok;
+do_compile([F | Fs], Opts) ->
+ io:format("Compiling ~p", [F]),
+ case compile:file(F, Opts) of
+ ok ->
+ io:format(" ok~n", []),
+ do_load(F, Opts),
+ do_compile(Fs, Opts);
+ {ok, _} ->
+ io:format(" ok~n", []),
+ do_load(F, Opts),
+ do_compile(Fs, Opts);
+ {ok, _, _} ->
+ io:format(" ok~n", []),
+ do_load(F, Opts),
+ do_compile(Fs, Opts);
+ Err ->
+ io:format(" error: ~p~n", [Err]),
+ Err
+ end.
+
+do_load(File, Opts) ->
+ case lists:member(load, Opts) of
+ true ->
+ io:format("Loading file ~p", [File]),
+ code:purge(File),
+ R = code:load_abs(File),
+ io:format("Loaded: ~p", [R]);
+ false ->
+ ok
+ end.
+
+
+%% Check that ErrList consists of exactly Num errors of type ErrType
+check_errors(Num, ErrType, ErrList) ->
+ Num = length(ErrList),
+ lists:foreach(fun(T) ->
+ case catch element(1, element(4, T)) of
+ ErrType -> ok;
+ Else ->
+ test_server:fail({bad, ErrType, Else})
+ end end, ErrList).
+
+to_list(X) when is_atom(X) -> atom_to_list(X);
+to_list(X) -> X.
+
+
+%% File must be an atom
+gen_struct_file(File, Mod) ->
+
+ ?line {ok, Fd} = file:open(to_list(File)++".erl", [write]),
+ io:format(Fd, "~n", []),
+ io:format(Fd, "-module(~p).~n", [Mod]),
+ io:format(Fd, "-export([test/0]).~n", []),
+ io:format(Fd, "-include(\"oe_struct.hrl\").~n", []),
+ io:format(Fd, "test() ->~n", []),
+ io:format(Fd, " A = #'S1'{a=99, b=$a, s=\"123456789\"},~n", []),
+ io:format(Fd, " B = #'S2'{a=9, b=#'S2_S3'{a=1, b=9, b1=5, c=$2},~n", []),
+ io:format(Fd, " c=[#'S1'{a=1}, #'S1'{a=2}],~n", []),
+ io:format(Fd,
+" c2=[#'S1'{a=2}, #'S1'{a=3}, #'S1'{a=2}, #'S1'{a=3}]},~n", []),
+ io:format(Fd, " C = #'S2_S3'{a=11, b=999, b1=19},~n", []),
+ io:format(Fd, " D = #s4{a=7},~n", []),
+ io:format(Fd, " E = {1, #'U1_S5'{a=3}},~n", []),
+ io:format(Fd, " F = {2, {$b, #'U1_U2_s6'{a=6, b=false}}},~n", []),
+ io:format(Fd, " ok.~n", []),
+ file:close(Fd).
+
+
+union_norm_files() -> ['oe_u_norm'].
+union_default_files() -> ['oe_u_default', i1].
+
+typeid_files() -> ['oe_typeid', 'M3_M2_M1_I1', 'M2_M1_I1', 'M1_I1', 'I1'].
+
+struct_norm_files() -> ['oe_struct'].
+oneway_norm_files() -> ['oe_one', 'I1'].
+oneway_followed_files() -> ['oe_one_followed', 'I1'].
+nasty_names_files() -> ['oe_nasty', 'I2', 'I1'].
+
+inherit_norm_files() -> [m1_I3, m1_I2, m1_I1, 'oe_inherit', 'I4', 'I3',
+ 'I2', 'I1'].
+
+forward_files() -> [i1, 'oe_forward'].
+enum_norm_files() -> ['oe_enum'].
+const_norm_files() -> ['oe_c_norm'].
+attr_norm_files() -> ['oe_attr', 'I1', 'I2'].
+type_norm_files() -> ['oe_type'].
+
+raises_reg_files() -> ['oe_raises_reg'].
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/ic/test/ic_SUITE_data/Corba.idl b/lib/ic/test/ic_SUITE_data/Corba.idl
new file mode 100644
index 0000000000..6b81132500
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/Corba.idl
@@ -0,0 +1,1013 @@
+// This file contains OMG IDL from CORBA V2.0, July 1995.
+// Includes IDL for CORBA Core
+// (Interface Repository, ORB Interface, Basic Object Adapter Interface)
+// and CORBA Interoperability (IOP, GIOP, IIOP, and DCE CIOP modules)
+
+// Complete OMG IDL for Interface Repository starts on pg 6-42, CORBA V2.0 July 1995
+// IRObject interface described on pg 6-9 CORBA V2.0, July 1995
+// Contained interface: pg 6-11 CORBA V2, 7-95
+// Container interface: pg 6-12 thru 6-15 CORBA V2, 7-95
+// IDLType interface: pg 6-15 CORBA V2, 7-95
+// Repository interface: pg 6-16 CORBA V2, 7-95
+// ModuleDef interface: pg 6-17 CORBA V2, 7-95
+// ConstantDef interface: pg 6-18 CORBA V2, 7-95
+// TypeDef interface: pg 6-19 CORBA V2, 7-95
+// StructDef interface: pg 6-19 CORBA V2, 7-95
+// UnionDef interface: pg 6-19 CORBA V2, 7-95
+// EnumDef interface: pg 6-20 CORBA V2, 7-95
+// AliasDef interface: pg 6-21 CORBA V2, 7-95
+// PrimitiveDef interface: pg 6-21 CORBA V2, 7-95
+// StringDef interface: pg 6-22 CORBA V2, 7-95
+// SequenceDef interface: pg 6-22 CORBA V2, 7-95
+// ArrayDef interface: pg 6-23 CORBA V2, 7-95
+// ExceptionDef interface: pg 6-24 CORBA V2, 7-95
+// AttributeDef interface: pg 6-25 CORBA V2, 7-95
+// OperationDef interface: pg 6-26 CORBA V2, 7-95
+// InterfaceDef interface: pg 6-28 CORBA V2, 7-95
+// TypeCode interface (PIDL): pg 6-34 CORBA V2, 7-95
+// ORB interface: pg 6-40 CORBA V2, 7-95
+
+#ifndef __CORBA_IDL
+#define __CORBA_IDL
+
+// #pragma prefix "omg.org"
+module CORBA {
+
+ interface TypeCode;
+ typedef string Identifier;
+ typedef string ScopedName;
+ typedef string RepositoryId;
+
+ /*
+ * start of section added by Christian Blum
+ */
+
+ typedef enum new_type {NO,USER,SYSTEM_EXCEPTION} exception_type;
+
+ /**
+ * no definition for this type
+ */
+ interface ImplementationDef
+ {
+ };
+
+ /**
+ * no definition for this type
+ */
+ //interface Principal
+ struct Principal
+ {
+ string str;
+ };
+
+ /**
+ * no definition for this type
+ */
+ interface Environment
+ {
+
+ };
+
+ typedef unsigned long Flags;
+ typedef unsigned long Status;
+
+ struct NamedValue // PIDL
+ {
+ Identifier name; // argument name
+ any argument; // argument
+ long len; // length/count of argument value
+ Flags arg_modes; // argument mode flags
+
+ };
+
+ typedef sequence<NamedValue> NVList; /* C */
+
+ interface Request // PIDL
+ {
+
+ Status add_arg (
+ in Identifier name, // argument name
+ in TypeCode arg_type, // argument datatype
+ // in void * value, // argument value to be added
+ in any value_LOOK_AT_SOURCE, // changed by blum
+ in long len, // length/count of argument value
+ in Flags arg_flags // argument flags
+ );
+
+ Status invoke (
+ in Flags invoke_flags // invocation flags
+ );
+
+ Status delete ();
+ Status send (
+ in Flags invoke_flags // invocation flags
+ );
+
+ Status get_response (
+ in Flags response_flags // response flags
+ );
+
+ };
+
+
+ interface Context // PIDL
+ {
+
+ Status set_one_value (
+ in Identifier prop_name, // property name to add
+ in string value // property value to add
+ );
+
+ Status set_values (
+ in NVList values // property values to be changed
+ );
+
+ Status get_values (
+ in Identifier start_scope, // search scope
+ in Flags op_flags, // operation flags
+ in Identifier prop_name, // name of property(s) to retrieve
+ out NVList values // requested property(s)
+ );
+
+ Status delete_values (
+ in Identifier prop_name // name of property(s) to delete
+ );
+
+ Status create_child (
+ in Identifier ctx_name, // name of context object
+ out Context child_ctx // newly created context object
+ );
+
+ Status delete (
+ in Flags del_flags // flags controlling deletion
+ );
+
+ };
+
+ /*
+ * end of section added by Christian Blum
+ */
+
+
+ enum DefinitionKind {
+ dk_none, dk_all,
+ dk_Attribute, dk_Constant, dk_Exception, dk_Interface,
+ dk_Module, dk_Operation, dk_Typedef,
+ dk_Alias, dk_Struct, dk_Union, dk_Enum,
+ dk_Primitive, dk_String, dk_Sequence, dk_Array,
+ dk_Repository
+ };
+
+
+ interface IRObject {
+ // read interface
+ readonly attribute DefinitionKind def_kind;
+
+ // write interface
+ void destroy ();
+ };
+
+
+
+ typedef string VersionSpec;
+
+ interface Contained;
+ interface Repository;
+ interface Container;
+
+ interface Contained : IRObject {
+ // read/write interface
+
+ attribute RepositoryId id;
+ attribute Identifier name;
+ attribute VersionSpec version;
+
+ // read interface
+
+ readonly attribute Container defined_in;
+ readonly attribute ScopedName absolute_name;
+ readonly attribute Repository containing_repository;
+
+ struct Description {
+ DefinitionKind kind;
+ any value;
+ };
+
+ Description describe ();
+
+ // write interface
+
+ void move (
+ in Container new_container,
+ in Identifier new_name,
+ in VersionSpec new_version
+ );
+ };
+
+
+ interface ModuleDef;
+ interface ConstantDef;
+ interface IDLType;
+ interface StructDef;
+ interface UnionDef;
+ interface EnumDef;
+ interface AliasDef;
+ interface InterfaceDef;
+ typedef sequence <InterfaceDef> InterfaceDefSeq;
+
+ typedef sequence <Contained> ContainedSeq;
+
+ struct StructMember {
+ Identifier name;
+ TypeCode type;
+ IDLType type_def;
+ };
+ typedef sequence <StructMember> StructMemberSeq;
+
+ struct UnionMember {
+ Identifier name;
+ any label;
+ TypeCode type;
+ IDLType type_def;
+ };
+ typedef sequence <UnionMember> UnionMemberSeq;
+
+ typedef sequence <Identifier> EnumMemberSeq;
+
+ interface Container : IRObject {
+ // read interface
+
+ Contained lookup ( in ScopedName search_name);
+
+ ContainedSeq contents (
+ in DefinitionKind limit_type,
+ in boolean exclude_inherited
+ );
+
+ ContainedSeq lookup_name (
+ in Identifier search_name,
+ in long levels_to_search,
+ in DefinitionKind limit_type,
+ in boolean exclude_inherited
+ );
+
+ struct Description {
+ Contained contained_object;
+ DefinitionKind kind;
+ any value;
+ };
+
+ typedef sequence<Description> DescriptionSeq;
+
+ DescriptionSeq describe_contents (
+ in DefinitionKind limit_type,
+ in boolean exclude_inherited,
+ in long max_returned_objs
+ );
+
+ // write interface
+
+ ModuleDef create_module (
+ in RepositoryId id,
+ in Identifier name,
+ in VersionSpec version
+ );
+
+ ConstantDef create_constant (
+ in RepositoryId id,
+ in Identifier name,
+ in VersionSpec version,
+ in IDLType type,
+ in any value
+ );
+
+ StructDef create_struct (
+ in RepositoryId id,
+ in Identifier name,
+ in VersionSpec version,
+ in StructMemberSeq members
+ );
+
+ UnionDef create_union (
+ in RepositoryId id,
+ in Identifier name,
+ in VersionSpec version,
+ in IDLType discriminator_type,
+ in UnionMemberSeq members
+ );
+
+ EnumDef create_enum (
+ in RepositoryId id,
+ in Identifier name,
+ in VersionSpec version,
+ in EnumMemberSeq members
+ );
+
+ AliasDef create_alias (
+ in RepositoryId id,
+ in Identifier name,
+ in VersionSpec version,
+ in IDLType original_type
+ );
+
+ InterfaceDef create_interface (
+ in RepositoryId id,
+ in Identifier name,
+ in VersionSpec version,
+ in InterfaceDefSeq base_interfaces
+ );
+ };
+
+
+
+ interface IDLType : IRObject {
+ readonly attribute TypeCode type;
+ };
+
+
+
+ interface PrimitiveDef;
+ interface StringDef;
+ interface SequenceDef;
+ interface ArrayDef;
+
+ enum PrimitiveKind {
+ pk_null, pk_void, pk_short, pk_long, pk_ushort, pk_ulong,
+ pk_float, pk_double, pk_boolean, pk_char, pk_octet,
+ pk_any, pk_TypeCode, pk_Principal, pk_string, pk_objref
+ };
+
+ interface Repository : Container {
+ // read interface
+
+ Contained lookup_id (in RepositoryId search_id);
+
+ PrimitiveDef get_primitive (in PrimitiveKind kind);
+
+ // write interface
+
+ StringDef create_string (in unsigned long bound);
+
+ SequenceDef create_sequence (
+ in unsigned long bound,
+ in IDLType element_type
+ );
+
+ ArrayDef create_array (
+ in unsigned long length,
+ in IDLType element_type
+ );
+ };
+
+
+ interface ModuleDef : Container, Contained {
+ };
+
+ struct ModuleDescription {
+ Identifier name;
+ RepositoryId id;
+ RepositoryId defined_in;
+ VersionSpec version;
+ };
+
+
+ interface ConstantDef : Contained {
+ readonly attribute TypeCode type;
+ attribute IDLType type_def;
+ attribute any value;
+ };
+
+ struct ConstantDescription {
+ Identifier name;
+ RepositoryId id;
+ RepositoryId defined_in;
+ VersionSpec version;
+ TypeCode type;
+ any value;
+ };
+
+
+ interface TypedefDef : Contained, IDLType {
+ };
+
+ struct TypeDescription {
+ Identifier name;
+ RepositoryId id;
+ RepositoryId defined_in;
+ VersionSpec version;
+ TypeCode type;
+ };
+
+
+ interface StructDef : TypedefDef {
+ attribute StructMemberSeq members;
+ };
+
+
+ interface UnionDef : TypedefDef {
+ readonly attribute TypeCode discriminator_type;
+ attribute IDLType discriminator_type_def;
+ attribute UnionMemberSeq members;
+ };
+
+
+ interface EnumDef : TypedefDef {
+ attribute EnumMemberSeq members;
+ };
+
+
+ interface AliasDef : TypedefDef {
+ attribute IDLType original_type_def;
+ };
+
+
+ interface PrimitiveDef: IDLType {
+ readonly attribute PrimitiveKind kind;
+ };
+
+
+ interface StringDef : IDLType {
+ attribute unsigned long bound;
+ };
+
+
+ interface SequenceDef : IDLType {
+ attribute unsigned long bound;
+ readonly attribute TypeCode element_type;
+ attribute IDLType element_type_def;
+ };
+
+ interface ArrayDef : IDLType {
+ attribute unsigned long length;
+ readonly attribute TypeCode element_type;
+ attribute IDLType element_type_def;
+ };
+
+
+ interface ExceptionDef : Contained {
+ readonly attribute TypeCode type;
+ attribute StructMemberSeq members;
+ };
+ struct ExceptionDescription {
+ Identifier name;
+ RepositoryId id;
+ RepositoryId defined_in;
+ VersionSpec version;
+ TypeCode type;
+ };
+
+
+
+ enum AttributeMode {ATTR_NORMAL, ATTR_READONLY};
+
+ interface AttributeDef : Contained {
+ readonly attribute TypeCode type;
+ attribute IDLType type_def;
+ attribute AttributeMode mode;
+ };
+
+ struct AttributeDescription {
+ Identifier name;
+ RepositoryId id;
+ RepositoryId defined_in;
+ VersionSpec version;
+ TypeCode type;
+ AttributeMode mode;
+ };
+
+
+
+ enum OperationMode {OP_NORMAL, OP_ONEWAY};
+
+ enum ParameterMode {PARAM_IN, PARAM_OUT, PARAM_INOUT};
+ struct ParameterDescription {
+ Identifier name;
+ TypeCode type;
+ IDLType type_def;
+ ParameterMode mode;
+ };
+ typedef sequence <ParameterDescription> ParDescriptionSeq;
+
+ typedef Identifier ContextIdentifier;
+ typedef sequence <ContextIdentifier> ContextIdSeq;
+
+ typedef sequence <ExceptionDef> ExceptionDefSeq;
+ typedef sequence <ExceptionDescription> ExcDescriptionSeq;
+
+ interface OperationDef : Contained {
+ readonly attribute TypeCode result;
+ attribute IDLType result_def;
+ attribute ParDescriptionSeq params;
+ attribute OperationMode mode;
+ attribute ContextIdSeq contexts;
+ attribute ExceptionDefSeq exceptions;
+ };
+
+ struct OperationDescription {
+ Identifier name;
+ RepositoryId id;
+ RepositoryId defined_in;
+ VersionSpec version;
+ TypeCode result;
+ OperationMode mode;
+ ContextIdSeq contexts;
+ ParDescriptionSeq parameters;
+ ExcDescriptionSeq exceptions;
+ };
+
+
+
+ typedef sequence <RepositoryId> RepositoryIdSeq;
+ typedef sequence <OperationDescription> OpDescriptionSeq;
+ typedef sequence <AttributeDescription> AttrDescriptionSeq;
+
+ interface InterfaceDef : Container, Contained, IDLType {
+ // read/write interface
+
+ attribute InterfaceDefSeq base_interfaces;
+
+ // read interface
+
+ boolean is_a (in RepositoryId interface_id);
+
+ struct FullInterfaceDescription {
+ Identifier name;
+ RepositoryId id;
+ RepositoryId defined_in;
+ VersionSpec version;
+ OpDescriptionSeq operations;
+ AttrDescriptionSeq attributes;
+ RepositoryIdSeq base_interfaces;
+ TypeCode type;
+ };
+
+ FullInterfaceDescription describe_interface();
+
+ // write interface
+
+ AttributeDef create_attribute (
+ in RepositoryId id,
+ in Identifier name,
+ in VersionSpec version,
+ in IDLType type,
+ in AttributeMode mode
+ );
+
+ OperationDef create_operation (
+ in RepositoryId id,
+ in Identifier name,
+ in VersionSpec version,
+ in IDLType result,
+ in OperationMode mode,
+ in ParDescriptionSeq params,
+ in ExceptionDefSeq exceptions,
+ in ContextIdSeq contexts
+ );
+ };
+
+ struct InterfaceDescription {
+ Identifier name;
+ RepositoryId id;
+ RepositoryId defined_in;
+ VersionSpec version;
+ RepositoryIdSeq base_interfaces;
+ };
+
+
+
+ enum TCKind {
+ tk_null, tk_void,
+ tk_short, tk_long, tk_ushort, tk_ulong,
+ tk_float, tk_double, tk_boolean, tk_char,
+ tk_octet, tk_any, tk_TypeCode, tk_Principal, tk_objref,
+ tk_struct, tk_union, tk_enum, tk_string,
+ tk_sequence, tk_array, tk_alias, tk_except
+ };
+
+ interface TypeCode { // PIDL
+ exception Bounds {};
+ exception BadKind {};
+
+ // for all TypeCode kinds
+ boolean equal (in TypeCode tc);
+ TCKind kind ();
+
+ // for tk_objref, tk_struct, tk_union, tk_enum, tk_alias, and tk_except
+ RepositoryId id () raises (BadKind);
+
+ // for tk_objref, tk_struct, tk_union, tk_enum, tk_alias, and tk_except
+ Identifier name () raises (BadKind);
+
+ // for tk_struct, tk_union, tk_enum, and tk_except
+ unsigned long member_count () raises (BadKind);
+ Identifier member_name (in unsigned long index) raises (BadKind, Bounds);
+
+ // for tk_struct, tk_union, and tk_except
+ TypeCode member_type (in unsigned long index) raises (BadKind, Bounds);
+
+ // for tk_union
+ any member_label (in unsigned long index) raises (BadKind, Bounds);
+ TypeCode discriminator_type () raises (BadKind);
+ long default_index () raises (BadKind);
+
+ // for tk_string, tk_sequence, and tk_array
+ unsigned long length () raises (BadKind);
+
+ // for tk_sequence, tk_array, and tk_alias
+ TypeCode content_type () raises (BadKind);
+
+ // deprecated interface
+ long param_count ();
+ any parameter (in long index) raises (Bounds);
+ };
+
+
+ /*
+ * following line added by Christian Blum
+ */
+ interface BOA;
+
+ interface ORB {
+ // other operations ...
+
+ TypeCode create_struct_tc (
+ in RepositoryId id,
+ in Identifier name,
+ in StructMemberSeq members
+ );
+
+ TypeCode create_union_tc (
+ in RepositoryId id,
+ in Identifier name,
+ in TypeCode discriminator_type,
+ in UnionMemberSeq members
+ );
+
+ TypeCode create_enum_tc (
+ in RepositoryId id,
+ in Identifier name,
+ in EnumMemberSeq members
+ );
+
+ TypeCode create_alias_tc (
+ in RepositoryId id,
+ in Identifier name,
+ in TypeCode original_type
+ );
+
+ TypeCode create_exception_tc (
+ in RepositoryId id,
+ in Identifier name,
+ in StructMemberSeq members
+ );
+
+ TypeCode create_interface_tc (
+ in RepositoryId id,
+ in Identifier name
+ );
+
+ TypeCode create_string_tc (
+ in unsigned long bound
+ );
+
+ TypeCode create_sequence_tc (
+ in unsigned long bound,
+ in TypeCode element_type
+ );
+
+ TypeCode create_recursive_sequence_tc (
+ in unsigned long bound,
+ in unsigned long offset
+ );
+
+ TypeCode create_array_tc (
+ in unsigned long length,
+ in TypeCode element_type
+ );
+
+ /*
+ * following line commented out by Christian Blum
+ */
+ // };
+
+ // The ORB interface (PIDL) is described in Chapter 7, CORBA V2.0 July 1995
+ // Object interface (object reference operations): pg 7-3 CORBA V2, 7-95
+ // ORB initialization: pg 7-7 CORBA V2, 7-95
+ // Object Adapter and Basic Object Adapter initialization: pg 7-8 CORBA V2 7-95
+ // Getting initial references: pg 7-10 CORBA V2 7-95
+ //PIDL
+
+ /*
+ * following line commented out by Christian Blum
+ */
+ //interface ORB {
+
+
+ string object_to_string (in Object obj);
+ Object string_to_object (in string str);
+
+ Status create_list (
+ in long count,
+ out NVList new_list
+ );
+ Status create_operation_list (
+ in OperationDef oper,
+ out NVList new_list
+ );
+ Status get_default_context (out Context ctx);
+
+ // Initializing the ORB
+ typedef string ORBid;
+ typedef sequence <string> arg_list;
+ ORB ORB_init (inout arg_list argv, in ORBid orb_identifier);
+
+ // Initializing an object adapter and the Basic Object Adapter
+ typedef string OAid;
+
+ // Template for OA initialization operations
+ // <OA> <OA>_init (inout arg_list argv,
+ // in OAid oa_identifier);
+
+
+
+ BOA BOA_init (inout arg_list argv,
+ in OAid boa_identifier);
+
+
+
+ // Getting initial object references
+ typedef string ObjectId;
+ typedef sequence <ObjectId> ObjectIdList;
+
+ exception InvalidName {};
+
+ ObjectIdList list_initial_services ();
+
+ Object resolve_initial_references (in ObjectId identifier)
+ raises (InvalidName);
+ };
+
+ // had to be changed..., Gerald Brose 1996
+ interface ORBject {
+
+ ImplementationDef get_implementation ();
+ InterfaceDef get_interface ();
+ boolean is_nil();
+ Object duplicate ();
+ void release ();
+ boolean is_a (in string logical_type_id);
+ boolean non_existent();
+ boolean is_equivalent (in Object other_object);
+ unsigned long hash(in unsigned long maximum);
+
+
+ Status create_request (
+ in Context ctx,
+ in Identifier operation,
+ in NVList arg_list,
+ inout NamedValue result,
+ out Request request,
+ in Flags req_flags
+ );
+ };
+
+
+ // Basic Object Adapter interface described in Chapter 8, CORBA V2.0, July 1995
+ // interface InterfaceDef; // from Interface Repository // PIDL
+ // interface ImplementationDef; // from Implementation Repository
+ // interface Object; // an object reference
+ // interface Principal; // for the authentication service
+ typedef sequence <octet, 1024> ReferenceData;
+
+ interface BOA {
+ Object create (
+ in ReferenceData id,
+ in InterfaceDef intf,
+ in ImplementationDef impl
+ );
+ void dispose (in Object obj);
+ ReferenceData get_id (in Object obj);
+
+ void change_implementation (in Object obj,
+ in ImplementationDef impl
+ );
+
+ Principal get_principal (in Object obj,
+ in Environment ev
+ );
+
+ void set_exception (in exception_type major, // NO, USER,
+ //or SYSTEM_EXCEPTION
+ in string userid, // exception type id
+ in any param_LOOK_AT_SOURCE
+ // in void *param // pointer to associated data
+ );
+
+ void impl_is_ready (in ImplementationDef impl);
+ void deactivate_impl (in ImplementationDef impl);
+ void obj_is_ready (in Object obj, in ImplementationDef impl);
+ void deactivate_obj (in Object obj);
+ };
+};
+
+// IOP module described in chap 10 CORBA V2, 7-95
+module IOP{ // IDL
+ //
+ // Standard Protocol Profile tag values
+ //
+ typedef unsigned long ProfileId;
+ const ProfileId TAG_INTERNET_IOP = 0;
+ const ProfileId TAG_MULTIPLE_COMPONENTS = 1;
+
+ struct TaggedProfile {
+ ProfileId tag;
+ sequence <octet> profile_data;
+ };
+
+ //
+ // an Interoperable Object Reference is a sequence of
+ // object-specific protocol profiles, plus a type ID.
+ //
+ struct IOR {
+ string type_id;
+ sequence <TaggedProfile> profiles;
+ };
+
+ //
+ // Standard way of representing multicomponent profiles.
+ // This would be encapsulated in a TaggedProfile.
+ //
+ typedef unsigned long ComponentId;
+ struct TaggedComponent {
+ ComponentId tag;
+ sequence <octet> component_data;
+ };
+ typedef sequence <TaggedComponent> MultipleComponentProfile;
+
+
+ typedef unsigned long ServiceID;
+
+ struct ServiceContext {
+ ServiceID context_id;
+ sequence <octet> context_data;
+ };
+ typedef sequence <ServiceContext> ServiceContextList;
+
+ const ServiceID TransactionService = 0;
+
+
+
+};
+// GIOP module described in CORBA V2, 7-95 chap 12
+// Complete IDL for GIOP module in CORBA
+// V2.0, 7-95 p 10-29
+// GIOP message header: CORBA V2, 7-95 p 12-16
+// GIOP request header: CORBA V2, 7-95 p 12-17
+// GIOP reply header: CORBA V2, 7-95 p 12-19
+// GIOP cancel request and locate request: CORBA V2, 7-95 pp 12-20 -- 12-21
+// GIOP locate reply: CORBA V2, 7-95 p 12-22
+module GIOP { // IDL
+ enum MsgType {
+ Request, Reply, CancelRequest,
+ LocateRequest, LocateReply,
+ CloseConnection, MessageError
+ };
+
+ struct Version {
+ char major;
+ char minor;
+ };
+
+ struct MessageHeader {
+ char magic [4];
+ Version GIOP_version;
+ boolean byte_order;
+ octet message_type;
+ unsigned long message_size;
+ };
+
+ struct RequestHeader {
+ ::IOP::ServiceContextList service_context;
+ unsigned long request_id;
+ boolean response_expected;
+ sequence <octet> object_key;
+ string operation;
+
+ /*
+ * ::CORBA:: added for correct scope
+ */
+ ::CORBA::Principal requesting_principal;
+ };
+
+ enum ReplyStatusType {
+ NO_EXCEPTION,
+ USER_EXCEPTION,
+ SYSTEM_EXCEPTION,
+ LOCATION_FORWARD
+ };
+
+ struct ReplyHeader {
+ ::IOP::ServiceContextList service_context;
+ unsigned long request_id;
+ ReplyStatusType reply_status;
+ };
+
+ struct CancelRequestHeader {
+ unsigned long request_id;
+ };
+
+ struct LocateRequestHeader {
+ unsigned long request_id;
+ sequence <octet> object_key;
+ };
+
+ enum LocateStatusType {
+ UNKNOWN_OBJECT,
+ OBJECT_HERE,
+ OBJECT_FORWARD
+ };
+
+ struct LocateReplyHeader {
+ unsigned long request_id;
+ LocateStatusType locate_status;
+ };
+};
+// IIOP module described in CORBA V2, 7-95 chap 12
+// Complete IDL for IIOP module: CORBA V2, 7-95 p 12-31
+module IIOP { // IDL
+ struct Version {
+ char major;
+ char minor;
+ };
+
+ struct ProfileBody {
+ Version iiop_version;
+ string host;
+ unsigned short port;
+ sequence <octet> object_key;
+ };
+};
+// DCE CIOP module described in CORBA V2, 7-95 chap 13
+// IDL for DCE CIOP module: CORBA V2, 7-95 p 13-2
+module DCE_CIOP {
+ struct InvokeRequestHeader {
+ boolean byte_order;
+ ::IOP::ServiceContextList service_context;
+ sequence <octet> object_key;
+ string endpoint_id;
+ string operation;
+ ::CORBA::Principal principal;
+ sequence <string> client_context;
+
+ // in and inout parameters follow
+ };
+ enum InvokeResponseStatus {
+ INVOKE_NO_EXCEPTION,
+ INVOKE_USER_EXCEPTION,
+ INVOKE_SYSTEM_EXCEPTION,
+ INVOKE_LOCATION_FORWARD,
+ INVOKE_TRY_AGAIN
+ };
+
+ struct InvokeResponseHeader {
+ boolean byte_order;
+ ::IOP::ServiceContextList service_context;
+ InvokeResponseStatus status;
+
+ // if status = INVOKE_NO_EXCEPTION,
+ // result then inouts and outs follow
+
+ // if status = INVOKE_USER_EXCEPTION or
+ // INVOKE_SYSTEM_EXCEPTION, an exception follows
+
+ // if status = INVOKE_LOCATION_FORWARD, an
+ // ::IOP::MultipleComponentsProfile follows
+ };
+
+ struct LocateRequestHeader {
+ boolean byte_order;
+ sequence <octet> object_key;
+ string endpoint_id;
+ string operation;
+
+ // no body follows
+ };
+
+ module IOP {
+
+ /*
+ * ::IOP:: added to get the right scope
+ */
+ const ::IOP::ComponentId TAG_OBJECT_KEY = 10;
+ const ::IOP::ComponentId TAG_ENDPOINT_ID = 11;
+ const ::IOP::ComponentId TAG_LOCATION_POLICY = 12;
+ // illegal IDL
+ /* const octet LOCATE_NEVER = 0;
+ const octet LOCATE_OBJECT = 1;
+ const octet LOCATE_OPERATION = 2;
+ const octet LOCATE_ALWAYS = 3;
+ */
+ };
+};
+
+#endif
diff --git a/lib/ic/test/ic_SUITE_data/Coss.idl b/lib/ic/test/ic_SUITE_data/Coss.idl
new file mode 100644
index 0000000000..c84d4a8247
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/Coss.idl
@@ -0,0 +1,1537 @@
+// This file contains OMG IDL and PIDL for the Common Object Services.
+// CosNaming Module, p 3-6 CORBAservices, Naming Service V1.0, 3/94
+
+// A few minor changes for the JacORB distribution:
+//
+// added am enclosing COSS module and changed scoped names accordingly
+//
+// corrected a few syntax errors
+//
+// commented out:
+// #includes
+// forward declaration of Object
+
+#include "Corba.idl"
+
+module COSS {
+
+module CosNaming {
+
+ typedef string Istring;
+ struct NameComponent {
+ Istring id;
+ Istring kind;
+ };
+
+ typedef sequence <NameComponent> Name;
+
+ enum BindingType {nobject, ncontext};
+
+ struct Binding {
+ Name binding_name;
+ BindingType binding_type;
+ };
+
+ typedef sequence <Binding> BindingList;
+ interface BindingIterator;
+
+ interface NamingContext {
+
+ enum NotFoundReason { missing_node, not_context, not_object};
+
+ exception NotFound {
+ NotFoundReason why;
+ Name rest_of_name;
+ };
+
+ exception CannotProceed {
+ NamingContext cxt;
+ Name rest_of_name;
+ };
+
+ exception InvalidName{};
+ exception AlreadyBound {};
+ exception NotEmpty{};
+
+ void bind(in Name n, in Object obj)
+ raises(NotFound, CannotProceed, InvalidName, AlreadyBound);
+ void rebind(in Name n, in Object obj)
+ raises(NotFound, CannotProceed, InvalidName);
+ void bind_context(in Name n, in NamingContext nc)
+ raises(NotFound, CannotProceed, InvalidName, AlreadyBound);
+ void rebind_context(in Name n, in NamingContext nc)
+ raises(NotFound, CannotProceed, InvalidName);
+ Object resolve (in Name n)
+ raises(NotFound, CannotProceed, InvalidName);
+ void unbind(in Name n)
+ raises(NotFound, CannotProceed, InvalidName);
+ NamingContext new_context();
+ NamingContext bind_new_context(in Name n)
+ raises(NotFound, AlreadyBound, CannotProceed, InvalidName);
+ void destroy( )
+ raises(NotEmpty);
+ void list (in unsigned long how_many,
+ out BindingList bl, out BindingIterator bi);
+ };
+
+ interface BindingIterator {
+ boolean next_one(out Binding b);
+ boolean next_n(in unsigned long how_many,
+ out BindingList bl);
+ void destroy();
+ };
+};
+
+// Names Library interface in PIDL, CORBAservices p 3- 14, Naming Service V1.0 3/94
+/*
+interface LNameComponent { // PIDL
+ exception NotSet{};
+ string get_id()
+ raises(NotSet);
+ void set_id(in string i);
+ string get_kind()
+ raises(NotSet);
+ void set_kind(in string k);
+ void destroy();
+};
+
+interface LName { // PIDL
+ exception NoComponent{};
+ exception OverFlow{};
+ exception InvalidName{};
+ LName insert_component(in unsigned long i,
+ in LNameComponent n)
+ raises(NoComponent, OverFlow);
+ LNameComponent get_component(in unsigned long i)
+ raises(NoComponent);
+ LNameComponent delete_component(in unsigned long i)
+ raises(NoComponent);
+ unsigned long num_components();
+ boolean equal(in LName ln);
+ boolean less_than(in LName ln);
+ Name to_idl_form()
+ raises(InvalidName);
+ void from_idl_form(in Name n);
+ void destroy();
+};
+
+LName create_lname(); // C/C++
+LNameComponent create_lname_component(); // C/C++
+*/
+
+// CosEventComm Module, CORBAservices p 4-8, Event Service V1.0 3/94
+
+module CosEventComm {
+
+ exception Disconnected{};
+
+ interface PushConsumer {
+ void push (in any data) raises(Disconnected);
+ void disconnect_push_consumer();
+ };
+
+ interface PushSupplier {
+ void disconnect_push_supplier();
+ };
+
+ interface PullSupplier {
+ any pull () raises(Disconnected);
+ any try_pull (out boolean has_event)
+ raises(Disconnected);
+ void disconnect_pull_supplier();
+ };
+
+ interface PullConsumer {
+ void disconnect_pull_consumer();
+ };
+
+};
+
+// CosEventChannelAdmin Module, p 4-15 CORBAservices, Event
+// Service V1.0, 3/94
+
+// #include "CosEventComm.idl"
+
+module CosEventChannelAdmin {
+
+ exception AlreadyConnected {};
+ exception TypeError {};
+
+ interface ProxyPushConsumer: ::COSS::CosEventComm::PushConsumer {
+ void connect_push_supplier(
+ in ::COSS::CosEventComm::PushSupplier push_supplier)
+ raises(AlreadyConnected);
+ };
+
+ interface ProxyPullSupplier: ::COSS::CosEventComm::PullSupplier {
+ void connect_pull_consumer(
+ in ::COSS::CosEventComm::PullConsumer pull_consumer)
+ raises(AlreadyConnected);
+ };
+
+ interface ProxyPullConsumer: ::COSS::CosEventComm::PullConsumer {
+ void connect_pull_supplier(
+ in ::COSS::CosEventComm::PullSupplier pull_supplier)
+ raises(AlreadyConnected,TypeError);
+ };
+
+ interface ProxyPushSupplier: ::COSS::CosEventComm::PushSupplier {
+ void connect_push_consumer(
+ in ::COSS::CosEventComm::PushConsumer
+ push_consumer)
+ raises(AlreadyConnected, TypeError);
+ };
+
+
+ interface ConsumerAdmin {
+ ProxyPushSupplier obtain_push_supplier();
+ ProxyPullSupplier obtain_pull_supplier();
+ };
+
+ interface SupplierAdmin {
+ ProxyPushConsumer obtain_push_consumer();
+ ProxyPullConsumer obtain_pull_consumer();
+ };
+
+ interface EventChannel {
+ ConsumerAdmin for_consumers();
+ SupplierAdmin for_suppliers();
+ void destroy();
+ };
+
+};
+
+
+// CosTyped Event Module, p 4-22 CORBAservices, Event Service
+// V1.0, 3/94
+
+// // #include "CosEventComm.idl"
+
+module CosTypedEventComm {
+
+ interface TypedPushConsumer : ::COSS::CosEventComm::PushConsumer {
+ Object get_typed_consumer();
+ };
+
+ interface TypedPullSupplier : ::COSS::CosEventComm::PullSupplier {
+ Object get_typed_supplier();
+ };
+
+};
+
+// CosTypedEventChannelAdmin Module, p 4- 25 CORBAservices,
+// Event Service V1.0, 3/94
+
+// // #include "CosEventChannel.idl"
+// // #include "CosTypedEventComm.idl"
+module CosTypedEventChannelAdmin {
+ exception InterfaceNotSupported {};
+ exception NoSuchImplementation {};
+ typedef string Key;
+
+ interface TypedProxyPushConsumer :
+ ::COSS::CosEventChannelAdmin::ProxyPushConsumer,
+ ::COSS::CosTypedEventComm::TypedPushConsumer { };
+
+ interface TypedProxyPullSupplier :
+ ::COSS::CosEventChannelAdmin::ProxyPullSupplier,
+ ::COSS::CosTypedEventComm::TypedPullSupplier { };
+
+ interface TypedSupplierAdmin :
+ ::COSS::CosEventChannelAdmin::SupplierAdmin {
+ TypedProxyPushConsumer obtain_typed_push_consumer(
+ in Key supported_interface)
+ raises(InterfaceNotSupported);
+ ::COSS::CosEventChannelAdmin::ProxyPullConsumer obtain_typed_pull_consumer (
+ in Key uses_interface)
+ raises(NoSuchImplementation);
+ };
+
+ interface TypedConsumerAdmin :
+ ::COSS::CosEventChannelAdmin::ConsumerAdmin {
+ TypedProxyPullSupplier obtain_typed_pull_supplier(
+ in Key supported_interface)
+ raises (InterfaceNotSupported);
+ ::COSS::CosEventChannelAdmin::ProxyPushSupplier obtain_typed_push_supplier(
+ in Key uses_interface)
+ raises(NoSuchImplementation);
+ };
+
+ interface TypedEventChannel {
+ TypedConsumerAdmin for_consumers();
+ TypedSupplierAdmin for_suppliers();
+ void destroy ();
+ };
+};
+
+
+// CosPersistencePID Module, p 5-20 CORBAservices,
+// Persistent Object Service V1.0, 3/94
+
+//#ifndef __COSPERSISTENCE
+//#define __COSPERSISTENCE
+
+module CosPersistencePID {
+
+ interface PID {
+ attribute string datastore_type;
+ string get_PIDString();
+ };
+};
+
+
+// CosPersistencePDS Module, p 5-20 CORBAservices,
+// Persistent Object Service V1.0, 3/94
+
+// #include "CosPersistencePID.idl"
+
+module CosPersistencePDS {
+
+// interface Object;
+ interface PDS {
+ PDS connect (in Object obj,
+ in ::COSS::CosPersistencePID::PID p);
+ void disconnect (in Object obj,
+ in ::COSS::CosPersistencePID::PID p);
+ void store (in Object obj,
+ in ::COSS::CosPersistencePID::PID p);
+ void restore (in Object obj,
+ in ::COSS::CosPersistencePID::PID p);
+ void delete (in Object obj,
+ in ::COSS::CosPersistencePID::PID p);
+ };
+};
+
+
+// CosPersistencePO Module, p 5-12 CORBAservices,
+// Persistent Object Service V1.0, 3/94
+
+// // #include "CosPersistencePDS.idl"
+// CosPersistencePDS.idl
+// // #includes CosPersistencePID.idl
+
+module CosPersistencePO {
+
+ interface PO {
+ attribute ::COSS::CosPersistencePID::PID p;
+ ::COSS::CosPersistencePDS::PDS connect (
+ in ::COSS::CosPersistencePID::PID p);
+ void disconnect (in ::COSS::CosPersistencePID::PID p);
+ void store (in ::COSS::CosPersistencePID::PID p);
+ void restore (in ::COSS::CosPersistencePID::PID p);
+ void delete (in ::COSS::CosPersistencePID::PID p);
+ };
+
+ interface SD {
+ void pre_store();
+ void post_restore();
+ };
+};
+
+
+// CosPersistencePOM Module, p 5-15 CORBAservices,
+// Persistent Object Service V1.0, 3/94
+
+// #include "CosPersistencePDS.idl"
+
+// CosPersistencePDS.idl // #includes CosPersistencePID.idl
+
+module CosPersistencePOM {
+
+// interface Object;
+
+ interface POM {
+ ::COSS::CosPersistencePDS::PDS connect (
+ in Object obj,
+ in ::COSS::CosPersistencePID::PID p);
+ void disconnect (
+ in Object obj,
+ in ::COSS::CosPersistencePID::PID p);
+ void store (
+ in Object obj,
+ in ::COSS::CosPersistencePID::PID p);
+ void restore (
+ in Object obj,
+ in ::COSS::CosPersistencePID::PID p);
+ void delete (
+ in Object obj,
+ in ::COSS::CosPersistencePID::PID p);
+ };
+ };
+
+// CosPersistencePDS_DA Module, p 5-22 CORBAservices,
+// Persistent Object Service, V1.0, 3/94
+
+// #include "CosPersistencePDS.idl"
+// CosPersistencePDS.idl // #includes CosPersistencePID.idl
+
+module CosPersistencePDS_DA {
+
+ typedef string DAObjectID;
+
+ interface PID_DA : ::COSS::CosPersistencePID::PID {
+ attribute DAObjectID oid;
+ };
+
+ interface DAObject {
+ boolean dado_same(in DAObject d);
+ DAObjectID dado_oid();
+ PID_DA dado_pid();
+ void dado_remove();
+ void dado_free();
+ };
+
+ interface DAObjectFactory {
+ DAObject create();
+ };
+
+ interface DAObjectFactoryFinder {
+ DAObjectFactory find_factory(in string key);
+ };
+
+ interface PDS_DA : ::COSS::CosPersistencePDS::PDS {
+ DAObject get_data();
+ void set_data(in DAObject new_data);
+ DAObject lookup(in DAObjectID id);
+ PID_DA get_pid();
+ PID_DA get_object_pid(in DAObject dao);
+ DAObjectFactoryFinder data_factories();
+ };
+
+ typedef sequence<string> AttributeNames;
+ interface DynamicAttributeAccess {
+ AttributeNames attribute_names();
+ any attribute_get(in string name);
+ void attribute_set(in string name, in any value);
+ };
+
+ typedef string ClusterID;
+ typedef sequence<ClusterID> ClusterIDs;
+ interface PDS_ClusteredDA : PDS_DA{
+ ClusterID cluster_id();
+ string cluster_kind();
+ ClusterIDs clusters_of();
+ PDS_ClusteredDA create_cluster(in string kind);
+ PDS_ClusteredDA open_cluster(in ClusterID cluster);
+ PDS_ClusteredDA copy_cluster(
+ in PDS_DA source);
+ };
+};
+
+// CosPersistenceDDO Module, p 5-32 CORBAservices, Persistent Object Service V1.0, 3/94
+
+// #include "CosPersistencePID.idl"
+module CosPersistenceDDO {
+
+ interface DDO {
+ attribute string object_type;
+ attribute ::COSS::CosPersistencePID::PID p;
+ short add_data();
+ short add_data_property (in short data_id);
+ short get_data_count();
+ short get_data_property_count (in short data_id);
+ void get_data_property (in short data_id,
+ in short property_id,
+ out string property_name,
+ out any property_value);
+ void set_data_property (in short data_id,
+ in short property_id,
+ in string property_name,
+ in any property_value);
+ void get_data (in short data_id,
+ out string data_name,
+ out any data_value);
+ void set_data (in short data_id,
+ in string data_name,
+ in any data_value);
+ };
+};
+
+// CosPersistenceDS_CLI module, p 5-34 CORBAservices,
+// Persistent Object Service V1.0, 3/94
+
+// #include "CosPersistenceDDO.idl"
+// CosPersistenceDDO.idl // #includes CosPersistencePID.idl
+
+module CosPersistenceDS_CLI {
+ interface UserEnvironment {
+ void set_option (in long option,in any value);
+ void get_option (in long option,out any value);
+ void release();
+ };
+
+ interface Connection {
+ void set_option (in long option,in any value);
+ void get_option (in long option,out any value);
+ };
+
+ interface ConnectionFactory {
+ Connection create_object (
+ in UserEnvironment user_envir);
+ };
+
+ interface Cursor {
+ void set_position (in long position,in any value);
+ ::COSS::CosPersistenceDDO::DDO fetch_object();
+ };
+
+ interface CursorFactory {
+ Cursor create_object (
+ in Connection connection);
+ };
+
+ interface PID_CLI : ::COSS::CosPersistencePID::PID {
+ attribute string datastore_id;
+ attribute string id;
+ };
+
+
+
+ interface Datastore_CLI {
+ void connect (in Connection connection,
+ in string datastore_id,
+ in string user_name,
+ in string authentication);
+ void disconnect (in Connection connection);
+ Connection get_connection (
+ in string datastore_id,
+ in string user_name);
+ void add_object (in Connection connection,
+ in ::COSS::CosPersistenceDDO::DDO data_obj);
+ void delete_object (
+ in Connection connection,
+ in ::COSS::CosPersistenceDDO::DDO data_obj);
+ void update_object (
+ in Connection connection,
+ in ::COSS::CosPersistenceDDO::DDO data_obj);
+ void retrieve_object(
+ in Connection connection,
+ in ::COSS::CosPersistenceDDO::DDO data_obj);
+ Cursor select_object(
+ in Connection connection,
+ in string key);
+ void transact (in UserEnvironment user_envir,
+ in short completion_type);
+ void assign_PID (in PID_CLI p);
+ void assign_PID_relative (
+ in PID_CLI source_pid,
+ in PID_CLI target_pid);
+ boolean is_identical_PID (
+ in PID_CLI pid_1,
+ in PID_CLI pid_2);
+ string get_object_type (in PID_CLI p);
+ void register_mapping_schema (in string schema_file);
+ Cursor execute (in Connection connection,
+ in string command);
+ };
+
+};
+
+
+// CosLifeCycle Module, p 6-10 CORBAservices, LifeCycle Service V1.0, 3/94
+
+// #include "Naming.idl"
+
+module CosLifeCycle
+{
+ typedef ::COSS::CosNaming::Name Key;
+ typedef Object Factory;
+ typedef sequence <Factory> Factories;
+ typedef struct NVP {
+ ::COSS::CosNaming::Istring name;
+ any value;
+ } NameValuePair;
+ typedef sequence <NameValuePair> Criteria;
+
+ exception NoFactory {
+ Key search_key;
+ };
+ exception NotCopyable { string reason; };
+ exception NotMovable { string reason; };
+ exception NotRemovable { string reason; };
+ exception InvalidCriteria{
+ Criteria invalid_criteria;
+ };
+ exception CannotMeetCriteria {
+ Criteria unmet_criteria;
+ };
+
+
+ interface FactoryFinder {
+ Factories find_factories(in Key factory_key)
+ raises(NoFactory);
+ };
+
+ interface LifeCycleObject {
+ LifeCycleObject copy(in FactoryFinder there,
+ in Criteria the_criteria)
+ raises(NoFactory, NotCopyable, InvalidCriteria,
+ CannotMeetCriteria);
+ void move(in FactoryFinder there,
+ in Criteria the_criteria)
+ raises(NoFactory, NotMovable, InvalidCriteria,
+ CannotMeetCriteria);
+ void remove()
+ raises(NotRemovable);
+ };
+
+ interface GenericFactory {
+ boolean supports(in Key k);
+ Object create_object(
+ in Key k,
+ in Criteria the_criteria)
+ raises (NoFactory, InvalidCriteria,
+ CannotMeetCriteria);
+ };
+};
+
+
+
+// LifeCycleService Module, p 6- 55 CORBAservices, Life Cycle
+// Service V1.0, 3/94
+
+// #include "LifeCycle.idl"
+
+module LifeCycleService {
+
+ typedef sequence <::COSS::CosLifeCycle::NameValuePair> PolicyList;
+ typedef sequence <::COSS::CosLifeCycle::Key> Keys;
+ typedef sequence <::COSS::CosLifeCycle::NameValuePair> PropertyList;
+ typedef sequence <::COSS::CosNaming::NameComponent> NameComponents;
+
+ interface LifeCycleServiceAdmin {
+
+ attribute PolicyList policies;
+
+ void bind_generic_factory(
+ in ::COSS::CosLifeCycle::GenericFactory gf,
+ in ::COSS::CosNaming::NameComponent name,
+ in Keys key_set,
+ in PropertyList other_properties)
+ raises (::COSS::CosNaming::NamingContext::AlreadyBound, ::COSS::CosNaming::NamingContext::InvalidName);
+
+ void unbind_generic_factory(
+ in ::COSS::CosNaming::NameComponent name)
+ raises (::COSS::CosNaming::NamingContext::NotFound, ::COSS::CosNaming::NamingContext::InvalidName);
+
+ ::COSS::CosLifeCycle::GenericFactory resolve_generic_factory(
+ in ::COSS::CosNaming::NameComponent name)
+ raises (::COSS::CosNaming::NamingContext::NotFound, ::COSS::CosNaming::NamingContext::InvalidName);
+
+ NameComponents list_generic_factories();
+
+ boolean match_service (in ::COSS::CosLifeCycle::GenericFactory f);
+
+ string get_hint();
+
+ void get_link_properties(
+ in ::COSS::CosNaming::NameComponent name,
+ out Keys key_set,
+ out PropertyList other_properties)
+ raises (::COSS::CosNaming::NamingContext::NotFound, ::COSS::CosNaming::NamingContext::InvalidName);
+ };
+};
+
+// CosTransactions Module, p 10-66
+// CORBAservices, Transaction Service V1.0, 3/94
+
+module CosTransactions {
+// DATATYPES
+enum Status {
+ StatusActive,
+ StatusMarkedRollback,
+ StatusPrepared,
+ StatusCommitted,
+ StatusRolledBack,
+ StatusUnknown,
+ StatusNoTransaction
+};
+
+enum Vote {
+ VoteCommit,
+ VoteRollback,
+ VoteReadOnly
+};
+
+// Standard exceptions
+exception TransactionRequired {};
+exception TransactionRolledBack {};
+exception InvalidTransaction {};
+
+// Heuristic exceptions
+exception HeuristicRollback {};
+exception HeuristicCommit {};
+exception HeuristicMixed {};
+exception HeuristicHazard {};
+
+// Exception from Orb operations
+exception WrongTransaction {};
+
+// Other transaction-specific exceptions
+exception SubtransactionsUnavailable {};
+exception NotSubtransaction {};
+exception Inactive {};
+exception NotPrepared {};
+exception NoTransaction {};
+exception InvalidControl {};
+exception Unavailable {};
+
+// Forward references for interfaces defined later in module
+interface Control;
+interface Terminator;
+interface Coordinator;
+interface Resource;
+interface RecoveryCoordinator;
+interface SubtransactionAwareResource;
+interface TransactionFactory;
+interface TransactionalObject;
+interface Current;
+
+// Current transaction pseudo object (PIDL)
+ interface Current {
+ void begin()
+ raises(SubtransactionsUnavailable);
+ void commit(in boolean report_heuristics)
+ raises(
+ NoTransaction,
+ HeuristicMixed,
+ HeuristicHazard
+ );
+ void rollback()
+ raises(NoTransaction);
+ void rollback_only()
+ raises(NoTransaction);
+
+ Status get_status();
+ string get_transaction_name();
+ void set_timeout(in unsigned long seconds);
+
+ Control get_control();
+ Control suspend();
+ void resume(in Control which)
+ raises(InvalidControl);
+ };
+
+ interface TransactionFactory {
+ Control create(in unsigned long time_out);
+ };
+
+ interface Control {
+ Terminator get_terminator()
+ raises(Unavailable);
+ Coordinator get_coordinator()
+ raises(Unavailable);
+ };
+
+ interface Terminator {
+ void commit(in boolean report_heuristics)
+ raises(
+ HeuristicMixed,
+ HeuristicHazard
+ );
+ void rollback();
+ };
+
+
+ interface Coordinator {
+
+ Status get_status();
+ Status get_parent_status();
+ Status get_top_level_status();
+
+ boolean is_same_transaction(in Coordinator tc);
+ boolean is_related_transaction(in Coordinator tc);
+ boolean is_ancestor_transaction(in Coordinator tc);
+ boolean is_descendant_transaction(in Coordinator tc);
+ boolean is_top_level_transaction();
+
+ unsigned long hash_transaction();
+ unsigned long hash_top_level_tran();
+
+ RecoveryCoordinator register_resource(in Resource r)
+ raises(Inactive);
+
+ void register_subtran_aware(in SubtransactionAwareResource r)
+ raises(Inactive, NotSubtransaction);
+
+ void rollback_only()
+ raises(Inactive);
+
+ string get_transaction_name();
+
+ Control create_subtransaction()
+ raises(SubtransactionsUnavailable, Inactive);
+ };
+
+ interface RecoveryCoordinator {
+ Status replay_completion(in Resource r)
+ raises(NotPrepared);
+ };
+
+}; // end module CosTransactions
+
+
+// CosConcurrency Control Module, p 7-8 CORBAservices,
+// Concurrency Control Service V1.0, 3/94
+
+// #include <CosTransactions.idl>
+module CosConcurrencyControl {
+
+ enum lock_mode {
+ read,
+ write,
+ upgrade,
+ intention_read,
+ intention_write
+ };
+
+ exception LockNotHeld{};
+
+ interface LockCoordinator
+ {
+ void drop_locks();
+ };
+
+ interface LockSet
+ {
+ void lock(in lock_mode mode);
+ boolean try_lock(in lock_mode mode);
+
+ void unlock(in lock_mode mode)
+ raises(LockNotHeld);
+ void change_mode(in lock_mode held_mode,
+ in lock_mode new_mode)
+ raises(LockNotHeld);
+ LockCoordinator get_coordinator(
+ in ::COSS::CosTransactions::Coordinator which);
+ };
+
+ interface TransactionalLockSet
+ {
+ void lock(in ::COSS::CosTransactions::Coordinator current,
+ in lock_mode mode);
+ boolean try_lock(in ::COSS::CosTransactions::Coordinator current,
+ in lock_mode mode);
+ void unlock(in ::COSS::CosTransactions::Coordinator current,
+ in lock_mode mode)
+ raises(LockNotHeld);
+ void change_mode(in ::COSS::CosTransactions::Coordinator current,
+ in lock_mode held_mode,
+ in lock_mode new_mode)
+ raises(LockNotHeld);
+ LockCoordinator get_coordinator(
+ in ::COSS::CosTransactions::Coordinator which);
+ };
+
+ interface LockSetFactory
+ {
+ LockSet create();
+ LockSet create_related(in LockSet which);
+ TransactionalLockSet create_transactional();
+ TransactionalLockSet create_transactional_related(in
+ TransactionalLockSet which);
+ };
+};
+
+// CosObjectIdentity Module, p 9-19 CORBAservices, Relationship
+// Service V1.0, 3/94
+
+
+module CosObjectIdentity {
+
+ typedef unsigned long ObjectIdentifier;
+
+ interface IdentifiableObject {
+ readonly attribute ObjectIdentifier constant_random_id;
+ boolean is_identical (
+ in IdentifiableObject other_object);
+ };
+
+};
+
+
+// CosRelationships Module, p 9-21 CORBAservices, Relationship
+// Service V1.0, 3/94
+
+// #include <ObjectIdentity.idl>
+
+module CosRelationships {
+
+ interface RoleFactory;
+ interface RelationshipFactory;
+ interface Relationship;
+ interface Role;
+ interface RelationshipIterator;
+
+ typedef Object RelatedObject;
+ typedef sequence<Role> Roles;
+ typedef string RoleName;
+ typedef sequence<RoleName> RoleNames;
+
+ struct NamedRole {RoleName name; Role aRole;};
+ typedef sequence<NamedRole> NamedRoles;
+
+ struct RelationshipHandle {
+ Relationship the_relationship;
+ ::COSS::CosObjectIdentity::ObjectIdentifier constant_random_id;
+ };
+ typedef sequence<RelationshipHandle> RelationshipHandles;
+
+ interface RelationshipFactory {
+ struct NamedRoleType {
+ RoleName name;
+ ::CORBA::InterfaceDef named_role_type;
+ };
+ typedef sequence<NamedRoleType> NamedRoleTypes;
+ readonly attribute ::CORBA::InterfaceDef relationship_type;
+ readonly attribute unsigned short degree;
+ readonly attribute NamedRoleTypes named_role_types;
+ exception RoleTypeError {NamedRoles culprits;};
+ exception MaxCardinalityExceeded {
+ NamedRoles culprits;};
+ exception DegreeError {unsigned short required_degree;};
+ exception DuplicateRoleName {NamedRoles culprits;};
+ exception UnknownRoleName {NamedRoles culprits;};
+
+ Relationship create (in NamedRoles named_roles)
+ raises (RoleTypeError,
+ MaxCardinalityExceeded,
+ DegreeError,
+ DuplicateRoleName,
+ UnknownRoleName);
+ };
+
+ interface Relationship :
+ ::COSS::CosObjectIdentity::IdentifiableObject {
+ exception CannotUnlink {
+ Roles offending_roles;
+ };
+ readonly attribute NamedRoles named_roles;
+ void destroy () raises(CannotUnlink);
+ };
+
+ interface Role {
+ exception UnknownRoleName {};
+ exception UnknownRelationship {};
+ exception RelationshipTypeError {};
+ exception CannotDestroyRelationship {
+ RelationshipHandles offenders;
+ };
+ exception ParticipatingInRelationship {
+ RelationshipHandles the_relationships;
+ };
+ readonly attribute RelatedObject related_object;
+ RelatedObject get_other_related_object (
+ in RelationshipHandle rel,
+ in RoleName target_name)
+ raises (UnknownRoleName,
+ UnknownRelationship);
+ Role get_other_role (in RelationshipHandle rel,
+ in RoleName target_name)
+ raises (UnknownRoleName, UnknownRelationship);
+ void get_relationships (
+ in unsigned long how_many,
+ out RelationshipHandles rels,
+ out RelationshipIterator iterator);
+ void destroy_relationships()
+ raises(CannotDestroyRelationship);
+ void destroy() raises(ParticipatingInRelationship);
+ boolean check_minimum_cardinality ();
+ void link (in RelationshipHandle rel,
+ in NamedRoles named_roles)
+ raises(RelationshipFactory::MaxCardinalityExceeded,
+ RelationshipTypeError);
+ void unlink (in RelationshipHandle rel)
+ raises (UnknownRelationship);
+ };
+
+ interface RoleFactory {
+ exception NilRelatedObject {};
+ exception RelatedObjectTypeError {};
+ readonly attribute ::CORBA::InterfaceDef role_type;
+ readonly attribute unsigned long max_cardinality;
+ readonly attribute unsigned long min_cardinality;
+// the following isn't allowed in IDL,
+// readonly attribute sequence <::CORBA::InterfaceDef> related_object_types;
+ typedef sequence <::CORBA::InterfaceDef> InterfaceDefSeq;
+ readonly attribute InterfaceDefSeq related_object_types;
+ Role create_role (in RelatedObject related_object)
+ raises (NilRelatedObject, RelatedObjectTypeError);
+ };
+
+ interface RelationshipIterator {
+ boolean next_one (out RelationshipHandle rel);
+ boolean next_n (in unsigned long how_many,
+ out RelationshipHandles rels);
+ void destroy ();
+ };
+
+};
+
+// CosCompoundExternalization Module, p 8-20 CORBAservices,
+// Externalization Service V1.0, 3/94
+
+// #include <Graphs.idl>
+// #include <Stream.idl>
+
+// CosGraphs Module, p 9-39 CORBAservices, Relationship Service
+// V1.0, 3/94
+
+// #include <Relationships.idl>
+// #include <ObjectIdentity.idl>
+
+module CosGraphs {
+
+ interface TraversalFactory;
+ interface Traversal;
+ interface TraversalCriteria;
+ interface Node;
+ interface NodeFactory;
+ interface Role;
+ interface EdgeIterator;
+
+ struct NodeHandle {
+ Node the_node;
+ ::COSS::CosObjectIdentity::ObjectIdentifier constant_random_id;
+ };
+ typedef sequence<NodeHandle> NodeHandles;
+
+ struct NamedRole {
+ Role the_role;
+ ::COSS::CosRelationships::RoleName the_name;
+ };
+ typedef sequence<NamedRole> NamedRoles;
+
+ struct EndPoint {
+ NodeHandle the_node;
+ NamedRole the_role;
+ };
+ typedef sequence<EndPoint> EndPoints;
+
+ struct Edge {
+ EndPoint from;
+ ::COSS::CosRelationships::RelationshipHandle the_relationship;
+ EndPoints relatives;
+ };
+ typedef sequence<Edge> Edges;
+
+ enum PropagationValue {deep, shallow, none, inhibit};
+ enum Mode {depthFirst, breadthFirst, bestFirst};
+
+ interface TraversalFactory {
+ Traversal create_traversal_on (
+ in NodeHandle root_node,
+ in TraversalCriteria the_criteria,
+ in Mode how);
+ };
+
+ interface Traversal {
+ typedef unsigned long TraversalScopedId;
+ struct ScopedEndPoint {
+ EndPoint point;
+ TraversalScopedId id;
+ };
+ typedef sequence<ScopedEndPoint> ScopedEndPoints;
+ struct ScopedRelationship {
+ ::COSS::CosRelationships::RelationshipHandle
+ scoped_relationship;
+ TraversalScopedId id;
+ };
+ struct ScopedEdge {
+ ScopedEndPoint from;
+ ScopedRelationship the_relationship;
+ ScopedEndPoints relatives;
+ };
+ typedef sequence<ScopedEdge> ScopedEdges;
+ boolean next_one (out ScopedEdge the_edge);
+ boolean next_n (in short how_many,
+ out ScopedEdges the_edges);
+ void destroy ();
+ };
+
+ interface TraversalCriteria {
+ struct WeightedEdge {
+ Edge the_edge;
+ unsigned long weight;
+ sequence<NodeHandle> next_nodes;
+ };
+ typedef sequence<WeightedEdge> WeightedEdges;
+ void visit_node(in NodeHandle a_node,
+ in Mode search_mode);
+ boolean next_one (out WeightedEdge the_edge);
+ boolean next_n (in short how_many,
+ out WeightedEdges the_edges);
+ void destroy();
+ };
+
+ interface Node: ::COSS::CosObjectIdentity::IdentifiableObject {
+ typedef sequence<Role> Roles;
+ exception NoSuchRole {};
+ exception DuplicateRoleType {};
+
+ readonly attribute ::COSS::CosRelationships::RelatedObject
+ related_object;
+ readonly attribute Roles roles_of_node;
+ Roles roles_of_type (
+ in ::CORBA::InterfaceDef role_type);
+ void add_role (in Role a_role)
+ raises (DuplicateRoleType);
+ void remove_role (in ::CORBA::InterfaceDef of_type)
+ raises (NoSuchRole);
+ };
+
+ interface NodeFactory {
+ Node create_node (in Object related_object);
+ };
+
+ interface Role : ::COSS::CosRelationships::Role {
+ void get_edges ( in long how_many,
+ out Edges the_edges,
+ out EdgeIterator the_rest);
+ };
+
+ interface EdgeIterator {
+ boolean next_one (out Edge the_edge);
+ boolean next_n ( in unsigned long how_many,
+ out Edges the_edges);
+ void destroy ();
+ };
+
+};
+
+
+
+// CosStream Module, 8-15 CORBAservices,
+// Externalization Service V1.0, 3/94
+
+// #include <LifeCycle.idl>
+// #include <ObjectIdentity.idl>
+// #include <CompoundExternalization.idl>
+module CosStream {
+ exception ObjectCreationError{};
+ exception StreamDataFormatError{};
+ interface StreamIO;
+
+ interface Streamable: ::COSS::CosObjectIdentity::IdentifiableObject
+ {
+ readonly attribute ::COSS::CosLifeCycle::Key external_form_id;
+ void externalize_to_stream(
+ in StreamIO targetStreamIO);
+ void internalize_from_stream(
+ in StreamIO sourceStreamIO,
+ in ::COSS::CosLifeCycle::FactoryFinder there)
+ raises( ::COSS::CosLifeCycle::NoFactory,
+ ObjectCreationError,
+ StreamDataFormatError );
+ };
+
+ interface StreamableFactory {
+ Streamable create_uninitialized();
+ };
+
+
+ interface StreamIO {
+ void write_string(in string aString);
+ void write_char(in char aChar);
+ void write_octet(in octet anOctet);
+ void write_unsigned_long(
+ in unsigned long anUnsignedLong);
+ void write_unsigned_short(
+ in unsigned short anUnsignedShort);
+ void write_long(in long aLong);
+ void write_short(in short aShort);
+ void write_float(in float aFloat);
+ void write_double(in double aDouble);
+ void write_boolean(in boolean aBoolean);
+ void write_object(in Streamable aStreamable);
+ // void write_graph(in ::COSS::CosCompoundExternalization::Node aNode);
+ string read_string()
+ raises(StreamDataFormatError);
+ char read_char()
+ raises(StreamDataFormatError );
+ octet read_octet()
+ raises(StreamDataFormatError );
+ unsigned long read_unsigned_long()
+ raises(StreamDataFormatError );
+ unsigned short read_unsigned_short()
+ raises( StreamDataFormatError );
+ long read_long()
+ raises(StreamDataFormatError );
+ short read_short()
+ raises(StreamDataFormatError );
+ float read_float()
+ raises(StreamDataFormatError );
+ double read_double()
+ raises(StreamDataFormatError );
+ boolean read_boolean()
+ raises(StreamDataFormatError );
+ Streamable read_object(
+ in ::COSS::CosLifeCycle::FactoryFinder there,
+ in Streamable aStreamable)
+ raises(StreamDataFormatError );
+// void read_graph(
+// in ::COSS::CosCompoundExternalization::Node starting_node,
+// in ::COSS::CosLifeCycle::FactoryFinder there)
+// raises(StreamDataFormatError );
+ };
+};
+
+module CosCompoundExternalization {
+ interface Node;
+ interface Role;
+ interface Relationship;
+ interface PropagationCriteriaFactory;
+
+ struct RelationshipHandle {
+ Relationship theRelationship;
+ ::COSS::CosObjectIdentity::ObjectIdentifier constantRandomId;
+ };
+
+ interface Node : ::COSS::CosGraphs::Node, ::COSS::CosStream::Streamable{
+ void externalize_node (in ::COSS::CosStream::StreamIO sio);
+ void internalize_node (in ::COSS::CosStream::StreamIO sio,
+ in ::COSS::CosLifeCycle::FactoryFinder there,
+ out ::COSS::CosGraphs::Node::Roles rolesOfNode)
+ raises (::COSS::CosLifeCycle::NoFactory);
+ };
+
+ interface Role : ::COSS::CosGraphs::Role {
+ void externalize_role (in ::COSS::CosStream::StreamIO sio);
+ void internalize_role (in ::COSS::CosStream::StreamIO sio);
+ ::COSS::CosGraphs::PropagationValue externalize_propagation (
+ in RelationshipHandle rel,
+ in ::COSS::CosRelationships::RoleName toRoleName,
+ out boolean sameForAll);
+ };
+
+ interface Relationship :
+ ::COSS::CosRelationships::Relationship {
+ void externalize_relationship (
+ in ::COSS::CosStream::StreamIO sio);
+ void internalize_relationship(
+ in ::COSS::CosStream::StreamIO sio,
+ in ::COSS::CosGraphs::NamedRoles newRoles);
+ ::COSS::CosGraphs::PropagationValue externalize_propagation (
+ in ::COSS::CosRelationships::RoleName fromRoleName,
+ in ::COSS::CosRelationships::RoleName toRoleName,
+ out boolean sameForAll);
+ };
+
+ interface PropagationCriteriaFactory {
+ ::COSS::CosGraphs::TraversalCriteria create_for_externalize( );
+ };
+
+};
+
+// CosExternalization Module, 8-12 CORBAservices,
+// Externalization Service V1.0, 3/94
+
+
+// #include <LifeCycle.idl>
+// #include <Stream.idl>
+module CosExternalization {
+ exception InvalidFileNameError{};
+ exception ContextAlreadyRegistered{};
+ interface Stream: ::COSS::CosLifeCycle::LifeCycleObject{
+ void externalize(
+ in ::COSS::CosStream::Streamable theObject);
+ ::COSS::CosStream::Streamable internalize(
+ in ::COSS::CosLifeCycle::FactoryFinder there)
+ raises( ::COSS::CosLifeCycle::NoFactory,
+ ::COSS::CosStream::StreamDataFormatError );
+ void begin_context()
+ raises( ContextAlreadyRegistered);
+ void end_context();
+ void flush();
+ };
+ interface StreamFactory {
+ Stream create();
+ };
+ interface FileStreamFactory {
+ Stream create(
+ in string theFileName)
+ raises( InvalidFileNameError );
+ };
+};
+
+// CosContainment Module, p 9- 48 CORBAservices, Relationship
+// Service V1.0, 3/94
+
+// #include <Graphs.idl>
+
+module CosContainment {
+
+ interface Relationship :
+ ::COSS::CosRelationships::Relationship {};
+
+ interface ContainsRole : ::COSS::CosGraphs::Role {};
+
+ interface ContainedInRole : ::COSS::CosGraphs::Role {};
+
+};
+
+// CosExternalizationContainment Module, p 8-26 CORBAservices,
+// Externalization Service V1.0, 3/94
+
+// #include <Containment.idl>
+// #include <CompoundExternalization.idl>
+
+module CosExternalizationContainment {
+
+ interface Relationship :
+ ::COSS::CosCompoundExternalization::Relationship,
+ ::COSS::CosContainment::Relationship {};
+
+ interface ContainsRole :
+ ::COSS::CosCompoundExternalization::Role,
+ ::COSS::CosContainment::ContainsRole {};
+
+ interface ContainedInRole :
+ ::COSS::CosCompoundExternalization::Role,
+ ::COSS::CosContainment::ContainedInRole {};
+};
+
+// CosReference Module, p 9-50 CORBAservices,
+// Relationship Service V1.0, 3/94
+
+// #include <Graphs.idl>
+
+module CosReference {
+
+ interface Relationship :
+ ::COSS::CosRelationships::Relationship {};
+
+ interface ReferencesRole : ::COSS::CosGraphs::Role {};
+
+ interface ReferencedByRole : ::COSS::CosGraphs::Role {};
+
+};
+
+// CosExternalizationReference Module, p 8-28 CORBAservices,
+// Externalization Service V1.0, 3/94
+
+// #include <Reference.idl>
+// #include <CompoundExternalization.idl>
+
+module CosExternalizationReference {
+
+ interface Relationship :
+ ::COSS::CosCompoundExternalization::Relationship,
+ ::COSS::CosReference::Relationship {};
+
+ interface ReferencesRole :
+ ::COSS::CosCompoundExternalization::Role,
+ ::COSS::CosReference::ReferencesRole {};
+
+ interface ReferencedByRole :
+ ::COSS::CosCompoundExternalization::Role,
+ ::COSS::CosReference::ReferencedByRole {};
+};
+
+// PIDL for CosTSInteroperation Module, p 10-59
+// CORBAservices, Transaction Service V1.0, 3/94
+module CosTSInteroperation { // PIDL
+ struct otid_t {
+ long formatID; /*format identifier. 0 is OSI TP */
+ long bequal_length;
+ sequence <octet> tid;
+ };
+ struct TransIdentity {
+ ::COSS::CosTransactions::Coordinator coordinator;
+ ::COSS::CosTransactions::Terminator terminator;
+ otid_t otid;
+ };
+ struct PropagationContext {
+ unsigned long timeout;
+ TransIdentity current;
+ sequence <TransIdentity> parents;
+ any implementation_specific_data;
+ };
+};
+
+// PIDL for CosTSPortability Module, p 10-63
+// CORBAservices, Transaction Service V1.0, 3/94
+
+module CosTSPortability { // PIDL
+ typedef long ReqId;
+
+ interface Sender {
+ void sending_request(in ReqId id,
+ out ::COSS::CosTSInteroperation::PropagationContext ctx);
+ void received_reply(in ReqId id,
+ in ::COSS::CosTSInteroperation::PropagationContext ctx,
+ in ::CORBA::Environment env);
+ };
+
+ interface Receiver {
+ void received_request(in ReqId id,
+ in ::COSS::CosTSInteroperation::PropagationContext ctx);
+ void sending_reply(in ReqId id,
+ out::COSS::CosTSInteroperation::PropagationContext ctx);
+ };
+};
+
+// CosCompoundLifeCycle Module, p 6-30 CORBAservices,
+// Life Cycle Service V1.0, 3/94
+
+// #include <LifeCycle.idl>
+// #include <Relationships.idl>
+// #include <Graphs.idl>
+
+module CosCompoundLifeCycle {
+ interface OperationsFactory;
+ interface Operations;
+ interface Node;
+ interface Role;
+ interface Relationship;
+ interface PropagationCriteriaFactory;
+
+ enum Operation {copy, move, remove};
+
+ struct RelationshipHandle {
+ Relationship the_relationship;
+ ::COSS::CosObjectIdentity::ObjectIdentifier constant_random_id;
+ };
+
+ interface OperationsFactory {
+ Operations create_compound_operations();
+ };
+
+ interface Operations {
+ Node copy (
+ in Node starting_node,
+ in ::COSS::CosLifeCycle::FactoryFinder there,
+ in ::COSS::CosLifeCycle::Criteria the_criteria)
+ raises (::COSS::CosLifeCycle::NoFactory,
+ ::COSS::CosLifeCycle::NotCopyable,
+ ::COSS::CosLifeCycle::InvalidCriteria,
+ ::COSS::CosLifeCycle::CannotMeetCriteria);
+ void move (
+ in Node starting_node,
+ in ::COSS::CosLifeCycle::FactoryFinder there,
+ in ::COSS::CosLifeCycle::Criteria the_criteria)
+ raises (::COSS::CosLifeCycle::NoFactory,
+ ::COSS::CosLifeCycle::NotMovable,
+ ::COSS::CosLifeCycle::InvalidCriteria,
+ ::COSS::CosLifeCycle::CannotMeetCriteria);
+ void remove (in Node starting_node)
+ raises (::COSS::CosLifeCycle::NotRemovable);
+ void destroy();
+ };
+
+ interface Node : ::COSS::CosGraphs::Node {
+ exception NotLifeCycleObject {};
+ void copy_node ( in ::COSS::CosLifeCycle::FactoryFinder there,
+ in ::COSS::CosLifeCycle::Criteria the_criteria,
+ out Node new_node,
+ out ::COSS::CosGraphs::Node::Roles roles_of_new_node)
+ raises (::COSS::CosLifeCycle::NoFactory,
+ ::COSS::CosLifeCycle::NotCopyable,
+ ::COSS::CosLifeCycle::InvalidCriteria,
+ ::COSS::CosLifeCycle::CannotMeetCriteria);
+ void move_node (in ::COSS::CosLifeCycle::FactoryFinder there,
+ in ::COSS::CosLifeCycle::Criteria the_criteria)
+ raises (::COSS::CosLifeCycle::NoFactory,
+ ::COSS::CosLifeCycle::NotMovable,
+ ::COSS::CosLifeCycle::InvalidCriteria,
+ ::COSS::CosLifeCycle::CannotMeetCriteria);
+ void remove_node ()
+ raises (::COSS::CosLifeCycle::NotRemovable);
+ ::COSS::CosLifeCycle::LifeCycleObject get_life_cycle_object()
+ raises (NotLifeCycleObject);
+ };
+
+ interface Role : ::COSS::CosGraphs::Role {
+ Role copy_role (in ::COSS::CosLifeCycle::FactoryFinder there,
+ in ::COSS::CosLifeCycle::Criteria the_criteria)
+ raises (::COSS::CosLifeCycle::NoFactory,
+ ::COSS::CosLifeCycle::NotCopyable,
+ ::COSS::CosLifeCycle::InvalidCriteria,
+ ::COSS::CosLifeCycle::CannotMeetCriteria);
+ void move_role (in ::COSS::CosLifeCycle::FactoryFinder there,
+ in ::COSS::CosLifeCycle::Criteria the_criteria)
+ raises (::COSS::CosLifeCycle::NoFactory,
+ ::COSS::CosLifeCycle::NotMovable,
+ ::COSS::CosLifeCycle::InvalidCriteria,
+ ::COSS::CosLifeCycle::CannotMeetCriteria);
+ ::COSS::CosGraphs::PropagationValue life_cycle_propagation (
+ in Operation op,
+ in RelationshipHandle rel,
+ in ::COSS::CosRelationships::RoleName to_role_name,
+ out boolean same_for_all);
+ };
+
+ interface Relationship :
+ ::COSS::CosRelationships::Relationship {
+ Relationship copy_relationship (
+ in ::COSS::CosLifeCycle::FactoryFinder there,
+ in ::COSS::CosLifeCycle::Criteria the_criteria,
+ in ::COSS::CosGraphs::NamedRoles new_roles)
+ raises (::COSS::CosLifeCycle::NoFactory,
+ ::COSS::CosLifeCycle::NotCopyable,
+ ::COSS::CosLifeCycle::InvalidCriteria,
+ ::COSS::CosLifeCycle::CannotMeetCriteria);
+ void move_relationship (
+ in ::COSS::CosLifeCycle::FactoryFinder there,
+ in ::COSS::CosLifeCycle::Criteria the_criteria)
+ raises (::COSS::CosLifeCycle::NoFactory,
+ ::COSS::CosLifeCycle::NotMovable,
+ ::COSS::CosLifeCycle::InvalidCriteria,
+ ::COSS::CosLifeCycle::CannotMeetCriteria);
+ ::COSS::CosGraphs::PropagationValue life_cycle_propagation (
+ in Operation op,
+ in ::COSS::CosRelationships::RoleName from_role_name,
+ in ::COSS::CosRelationships::RoleName to_role_name,
+ out boolean same_for_all);
+ };
+
+ interface PropagationCriteriaFactory {
+ ::COSS::CosGraphs::TraversalCriteria create(in Operation op);
+ };
+
+};
+
+// CosLifeCycleContainment Module, p 6-42 CORBAservices,
+// Life Cycle Service V1.0, 3/94
+
+// #include <Containment.idl>
+// #include <CompoundLifeCycle.idl>
+
+module CosLifeCycleContainment {
+
+ interface Relationship :
+ ::COSS::CosCompoundLifeCycle::Relationship,
+ ::COSS::CosContainment::Relationship {};
+
+ interface ContainsRole :
+ ::COSS::CosCompoundLifeCycle::Role,
+ ::COSS::CosContainment::ContainsRole {};
+
+ interface ContainedInRole :
+ ::COSS::CosCompoundLifeCycle::Role,
+ ::COSS::CosContainment::ContainedInRole {};
+};
+
+// CosLifeCycleReference Module, p 6-44 CORBAservices,
+// Life Cycle Service V1.0, 3/94
+
+// #include <Reference.idl>
+// #include <CompoundLifeCycle.idl>
+
+module CosLifeCycleReference {
+
+ interface Relationship :
+ ::COSS::CosCompoundLifeCycle::Relationship,
+ ::COSS::CosReference::Relationship {};
+
+ interface ReferencesRole :
+ ::COSS::CosCompoundLifeCycle::Role,
+ ::COSS::CosReference::ReferencesRole {};
+
+ interface ReferencedByRole :
+ ::COSS::CosCompoundLifeCycle::Role,
+ ::COSS::CosReference::ReferencedByRole {};
+};
+
+
+}; // end module COSS
diff --git a/lib/ic/test/ic_SUITE_data/attr.idl b/lib/ic/test/ic_SUITE_data/attr.idl
new file mode 100644
index 0000000000..c74223eca6
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/attr.idl
@@ -0,0 +1,29 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+interface I1 {
+ attribute long a1, a2;
+ attribute char a3;
+};
+
+interface I2 : I1 {
+ attribute short a4;
+ readonly attribute char a5;
+};
+
diff --git a/lib/ic/test/ic_SUITE_data/c_err1.idl b/lib/ic/test/ic_SUITE_data/c_err1.idl
new file mode 100644
index 0000000000..e1bc93dae8
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/c_err1.idl
@@ -0,0 +1,63 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+//
+// This file forces the bad_tk_match. This triggers when the type of
+// the expression does not match the declared type of the constant
+//
+
+const long c1 = TRUE;
+const unsigned short c1b= TRUE;
+const boolean c2 = +5;
+const long c3 = 'c';
+const float c5 = 3;
+const unsigned long c6 = -2; // Maybe not checked in compiler or suite
+
+const boolean c4 = 1 | 2;
+
+
+// Now define some correct constants for use in reference checking
+
+const long longC = -9;
+const short shortC = -9;
+const unsigned long ulongC = 1;
+const unsigned short ushortC = 0;
+
+const float floatC = 5.1;
+const double doubleC = -2.111;
+
+const boolean boolC = TRUE;
+
+const char charC = 'f';
+const string stringC = "hej";
+const string<9> stringCb = "hejdu";
+
+// Check the reference errors
+
+const long c19 = floatC;
+const short c20 = doubleC;
+const unsigned long c21 = charC;
+const unsigned short c22 = stringC;
+const float c23 = stringCb;
+const double c24 = boolC;
+const boolean c25 = longC;
+const char c26 = shortC;
+const string c27 = ushortC;
+const string<9> c28 = ulongC;
+const long c29 = 3+floatC;
diff --git a/lib/ic/test/ic_SUITE_data/c_err2.idl b/lib/ic/test/ic_SUITE_data/c_err2.idl
new file mode 100644
index 0000000000..8dac241c7f
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/c_err2.idl
@@ -0,0 +1,30 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+//
+// Checks bad type of operands
+//
+
+
+const long c1 = 1 + TRUE;
+const boolean c3 = TRUE | FALSE | 19.8;
+const long c4 = 1 << TRUE;
+const long c5 = TRUE >> TRUE;
+
+
diff --git a/lib/ic/test/ic_SUITE_data/c_err3.idl b/lib/ic/test/ic_SUITE_data/c_err3.idl
new file mode 100644
index 0000000000..dde9539f6f
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/c_err3.idl
@@ -0,0 +1,28 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+//
+// Checks ill-formed expressions (type conflict in operands)
+//
+
+
+const long c1 = 5|TRUE;
+const long c2 = 5&TRUE;
+const long c3 = 5^TRUE;
+
diff --git a/lib/ic/test/ic_SUITE_data/c_norm.idl b/lib/ic/test/ic_SUITE_data/c_norm.idl
new file mode 100644
index 0000000000..6f6ef8ff79
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/c_norm.idl
@@ -0,0 +1,163 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+//
+// Check normal values and expressions for constants
+//
+
+// Integer types
+const long co1 = 077;
+const long ch1 = 0xf1;
+const long ch2 = 0XAB;
+const long c1 = 1;
+const short c2 = 3;
+const unsigned long c3 = 1;
+const unsigned short c4 = 3;
+
+// Unary ops
+const long c1hb = -0x1;
+const long c1b = -1;
+const short c2b = -3;
+const long c1c = +1;
+const short c2c = +3;
+// ~ not supported
+
+// Check binary ops
+const long c1d = 9+1-3;
+const long c1hd = 9+1-0xf3;
+const short c2d = 7+3;
+const short c2e = 7*3;
+const long c1e = 1 | 7;
+const long c1f = 7 & 9;
+const long c1g = (1 | 7) & 9;
+const long c1h = 1^7;
+
+//floats
+const float c5 = 1.9;
+const double c6 = 1.9;
+const float c5b = -1.9;
+const double c6b = -1.9;
+
+// Check type operand casting
+const float c5c = 1/(9+2) * 2;
+const double c6c = 1.9-1;
+//const double c6d = 1; // Does not work yet
+
+// Booleans and expressions
+const boolean c7 = TRUE;
+const boolean c7b = FALSE;
+const boolean c7c = TRUE | FALSE;
+const boolean c7d = TRUE & FALSE;
+const boolean c7e = TRUE&TRUE | FALSE&TRUE;
+const boolean c7f = TRUE&TRUE ^ FALSE&TRUE;
+
+// Character and string
+const char c8 = 'c';
+const char c8b = '\n';
+const string c9 = "hej";
+const string<9> c9b = "hejdu";
+
+
+//
+// Check that value references work
+//
+
+const long rc1 = c1g;
+const long rc1h = c1h + 9;
+const short rc2 = c2;
+const unsigned long rc3 = c3;
+const unsigned short rc4 = c4;
+
+
+const float rc5c = c5c;
+const double rc6c = c6c;
+const double rc6d = c6c+1.3;
+
+const boolean rc7 = c7;
+const boolean rc7c = c7c | TRUE;
+
+const char rc8 = c8;
+const char rc8b = c8b;
+const string rc9 = c9;
+const string<9> rc9b = c9b;
+
+
+
+
+//
+// Now check that all typerefs work
+//
+
+typedef long longT;
+typedef short shortT;
+typedef unsigned long ulongT;
+typedef unsigned short ushortT;
+
+typedef float floatT;
+typedef double doubleT;
+
+typedef char charT;
+typedef string stringT;
+
+typedef boolean booleanT;
+
+const longT cc1 = 1;
+const shortT cc2 = 3;
+const ::longT cc1b = -1;
+const ::shortT cc2b = -3;
+
+const floatT cc5 = 1.9;
+const doubleT cc6 = 1.9;
+const floatT cc5b = -1.9;
+const doubleT cc6b = -1.9;
+const floatT cc5c = 1/(9+2) * 2;
+const doubleT cc6c = 1.9-1;
+
+const booleanT cc7 = TRUE;
+const booleanT cc7b = TRUE;
+const booleanT cc7c = TRUE | FALSE;
+const booleanT cc7d = TRUE & FALSE;
+const booleanT cc7e = TRUE&TRUE | FALSE&TRUE;
+
+
+const charT cc8 = 'c';
+const charT cc8b = '\n';
+const stringT cc9 = "hej";
+const stringT cc9b = "hejdu";
+
+
+//
+// Check value casting
+//
+const long longC = -9;
+const short shortC = -9;
+const unsigned long ulongC = 1;
+const unsigned short ushortC = 0;
+
+const float floatC = 5.1;
+const double doubleC = -2.111;
+
+const long c20 = shortC;
+const long c21 = ulongC;
+const long c22 = ushortC;
+const short c23 = ushortC;
+const double c34 = floatC;
+
+
+
diff --git a/lib/ic/test/ic_SUITE_data/enum.idl b/lib/ic/test/ic_SUITE_data/enum.idl
new file mode 100644
index 0000000000..c164e4bf74
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/enum.idl
@@ -0,0 +1,32 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+
+enum E1 {kalle, sune};
+
+enum E2 { el0, el1, el2, el3, el4, el5, el6, el7, el8, el9, el10, el11, el12, el13,
+el14, el15, el16, el17, el18, el19, el20, el21, el22, el23, el24, el25, el26, el27,
+el28, el29, el30, el31, el32, el33, el34, el35, el36, el37, el38, el39, el40, el41,
+el42, el43, el44, el45, el46, el47, el48, el49, el50, el51, el52, el53, el54, el55,
+el56, el57, el58, el59};
+
+
+
+
+
diff --git a/lib/ic/test/ic_SUITE_data/forward.idl b/lib/ic/test/ic_SUITE_data/forward.idl
new file mode 100644
index 0000000000..1e16265af5
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/forward.idl
@@ -0,0 +1,34 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+//
+// Check that forward declarations are handled correctly
+//
+
+
+interface i1;
+
+
+interface i1 {
+ typedef long T;
+};
+
+
+interface i1;
+
diff --git a/lib/ic/test/ic_SUITE_data/include.idl b/lib/ic/test/ic_SUITE_data/include.idl
new file mode 100644
index 0000000000..24022bfa1e
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/include.idl
@@ -0,0 +1,30 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+// Check that errors are given with the correct file name reference
+
+#include "include2.idl"
+
+
+typedef T1 T7;
+typedef long T7;
+typedef long T111;
+
+
+
diff --git a/lib/ic/test/ic_SUITE_data/include2.idl b/lib/ic/test/ic_SUITE_data/include2.idl
new file mode 100644
index 0000000000..2f8f7fd62c
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/include2.idl
@@ -0,0 +1,26 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+// Check that errors are given with the correct file name reference
+
+#include "include3.idl"
+
+
+typedef T7 T1;
+
diff --git a/lib/ic/test/ic_SUITE_data/include3.idl b/lib/ic/test/ic_SUITE_data/include3.idl
new file mode 100644
index 0000000000..c5f89c6c63
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/include3.idl
@@ -0,0 +1,25 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+// Check that errors are given with the correct file name reference
+
+typedef T7 T1;
+
+
+
diff --git a/lib/ic/test/ic_SUITE_data/inherit.idl b/lib/ic/test/ic_SUITE_data/inherit.idl
new file mode 100644
index 0000000000..71b79c8748
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/inherit.idl
@@ -0,0 +1,68 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+
+interface I1 {
+ typedef long T1;
+ typedef struct S1 {long a; boolean b;} T2;
+ typedef string StringT, StringT_arr[10];
+
+ T1 op1( in StringT a, inout char b, out StringT_arr c );
+ T2 op2( in char a, inout char b, out StringT_arr c );
+
+ const T1 LongC = 10;
+ const StringT StringC = "Hola bambino";
+
+};
+
+
+interface I2 : I1 {
+ T1 op3( in long a);
+
+ const long c1 = LongC;
+ const string c2 = StringC;
+};
+
+interface I3 : I1 {};
+
+interface I4 : I3, I2 {}; // Check that branced inherit works
+
+
+
+// Now use cnstants to check that inheritance works as expected
+
+module m1 {
+ interface I1 {
+ typedef long T1;
+
+ const T1 c1 = 9;
+ };
+
+ interface I2 : I1 {
+ const T1 c2 = c1+5; // c2 = 14
+ const long c3 = c2+c1+4; // c3 = 27
+ };
+
+ interface I3 : I2, I1 {
+ const long c1 = 50; // Overrides I1::c1
+ const T1 c4 = c1+c2+c3; // c4=91
+ const T1 c5 = I1::c1+c1+c2+c3; // 100
+ };
+};
+
diff --git a/lib/ic/test/ic_SUITE_data/inherit_err.idl b/lib/ic/test/ic_SUITE_data/inherit_err.idl
new file mode 100644
index 0000000000..4cfc3ffbff
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/inherit_err.idl
@@ -0,0 +1,71 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+//
+// Ops and attributes must not be redefined (shadowed)
+
+interface I1 {
+ long op1( in long a, inout char b, out boolean c );
+ long op2( in char a, inout char b, out boolean c );
+ attribute long a1, a2;
+ readonly attribute char a3;
+};
+
+interface I2 : I1 {
+ long op1( in float a, inout char b, out boolean c );
+ long op2( in char a, inout char b, out boolean c );
+ attribute long a1, a2;
+ readonly attribute char a3;
+};
+
+interface I3 : I1 {
+ long op3 (in string<19> b);
+};
+
+
+interface I4 : I3 {
+ long op1( in float a, inout char b, out boolean c );
+ long op2( in char a, inout char b, out boolean c );
+ attribute long a1, a2;
+ readonly attribute char a3;
+
+ long op3 (in string<19> b);
+};
+
+
+interface I11 {
+ long op1( in float a, inout char b, out boolean c );
+ long op2( in char a, inout char b, out boolean c );
+ attribute long a1, a2;
+ readonly attribute char a3;
+};
+
+
+
+interface I5 : I1, I11 {};
+
+interface I6 : I1 {
+ const long op1=0;
+ const long op2=0;
+ const long a1=0;
+ const long a2=0;
+ const long a3=0;
+};
+
+
diff --git a/lib/ic/test/ic_SUITE_data/inherit_warn.idl b/lib/ic/test/ic_SUITE_data/inherit_warn.idl
new file mode 100644
index 0000000000..502bfac8d4
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/inherit_warn.idl
@@ -0,0 +1,64 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+//
+// Checks that shadow warnings comes out as expected
+//
+
+
+interface I1 {
+ typedef long T1;
+ typedef struct S1 {long a; boolean b;} T2;
+ typedef string StringT, StringT_arr[10];
+
+ T1 op1( in StringT a, inout char b, out StringT_arr c );
+ T2 op2( in char a, inout char b, out StringT_arr c );
+
+ const T1 LongC = 10;
+ const StringT StringC = "Hola bambino";
+
+};
+
+
+interface I2 : I1 {
+ typedef char T1; // Shadows I1::T1
+ const boolean StringC = FALSE; // shadows I1::StringC
+
+ T1 op3( in long a);
+
+ const long c1 = LongC;
+ const boolean c2 = StringC;
+};
+
+interface I3 : I2 {}; // More shadows
+
+interface I4 : I1 {
+ T1 op4();
+ const T1 c2 = 66;
+};
+
+interface I5 : I4 {
+ typedef string T1; // Shadows I1::T1
+ const char LongC = 'a'; // Shadows I1::LongC
+};
+
+
+interface I6 : I4, I3 {
+};
+
diff --git a/lib/ic/test/ic_SUITE_data/mult_ids.idl b/lib/ic/test/ic_SUITE_data/mult_ids.idl
new file mode 100644
index 0000000000..46deaa9f55
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/mult_ids.idl
@@ -0,0 +1,92 @@
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+//
+// Check that multiply defined identifiers are detected
+//
+
+typedef long T1;
+typedef long T1;
+typedef long T2;
+exception T2 {};
+
+
+//Exceptions
+exception Exc1 {};
+exception Exc1 {};
+
+
+// Enums
+enum E1 {kalle};
+enum E1 {kalle};
+enum E2 {kalle, sune, kalle};
+
+
+// Structs
+struct S1 {long a;};
+struct S1 {long a;};
+struct S2 {long a; short a;};
+struct S3 {long a,b; short a;};
+struct S4 {long a,a; short a;};
+
+
+// Constants
+const long c1 = 0;
+const long c1 = 0;
+
+
+// Interfaces
+
+interface i1 {};
+interface i1 {};
+
+interface i2 {
+ attribute long a1;
+ attribute long a1;
+};
+
+interface i3 {
+ attribute long a1, a2;
+ attribute long a2;
+};
+
+interface i4 {
+ attribute long a1, a1;
+};
+
+interface i5 {
+ long op1();
+ long op1();
+
+ long op2(in long a, inout char a);
+};
+
+
+// Unions
+
+union U1 switch (long) {case 1: long a;};
+union U1 switch (long) {case 1: long a;};
+
+union U2 switch (long) {
+case 1: long a;
+default: char a;
+};
+
+
+
+
+
diff --git a/lib/ic/test/ic_SUITE_data/nasty.idl b/lib/ic/test/ic_SUITE_data/nasty.idl
new file mode 100644
index 0000000000..15fd523c0f
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/nasty.idl
@@ -0,0 +1,60 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+//
+// Checks nasty name collisions
+//
+
+typedef string T;
+
+
+#define nasty01 version
+#define nasty02 preproc
+#define nasty03 pragma
+#define nasty04 compile
+#define nasty05 if
+#define nasty06 receive
+#define nasty07 foldr
+#define nasty08 length
+#define nasty09 ID
+
+interface I1 {
+ attribute T nasty01;
+ attribute T nasty02;
+ attribute T nasty03;
+ attribute T nasty04;
+ attribute T nasty05;
+ attribute T nasty06;
+ attribute T nasty07;
+ attribute T nasty08;
+ attribute T nasty09;
+};
+
+interface I2 {
+ T nasty01();
+ T nasty02();
+ T nasty03();
+ T nasty04();
+ T nasty05();
+ T nasty06();
+ T nasty07();
+ T nasty08();
+ T nasty09();
+};
+
diff --git a/lib/ic/test/ic_SUITE_data/one.idl b/lib/ic/test/ic_SUITE_data/one.idl
new file mode 100644
index 0000000000..99281d6079
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/one.idl
@@ -0,0 +1,29 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+// Test oneway operations
+
+interface I1 {
+ long op1(in char a, inout boolean b, out string c);
+ oneway void op2(in char a, in boolean b, in string c);
+ oneway void op3();
+};
+
+
+
diff --git a/lib/ic/test/ic_SUITE_data/one_followed.idl b/lib/ic/test/ic_SUITE_data/one_followed.idl
new file mode 100644
index 0000000000..da8ee74e25
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/one_followed.idl
@@ -0,0 +1,54 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+// Test oneway operations followed by other operations
+
+interface I1 {
+ oneway void op1();
+ oneway void op2(in char a, in boolean b, in string c);
+ long op3(in char a, inout boolean b, out string c);
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/ic/test/ic_SUITE_data/one_out.idl b/lib/ic/test/ic_SUITE_data/one_out.idl
new file mode 100644
index 0000000000..65f177ff22
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/one_out.idl
@@ -0,0 +1,28 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+// Test oneway operations not using in out params
+
+interface I1 {
+ oneway void op1(in char a, inout boolean b, in string c);
+ oneway void op2(in char a, out boolean b, in string c);
+};
+
+
+
diff --git a/lib/ic/test/ic_SUITE_data/one_raises.idl b/lib/ic/test/ic_SUITE_data/one_raises.idl
new file mode 100644
index 0000000000..8290877363
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/one_raises.idl
@@ -0,0 +1,32 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+// Test oneway operations not using in out params
+
+exception hell {boolean burn; unsigned long for_how_long;};
+exception high_water {long mark;};
+
+interface I1 {
+ oneway void op1(in char a) raises (hell);
+ oneway void op2(in char a) raises (hell);
+ oneway void op3() raises (hell, high_water);
+};
+
+
+
diff --git a/lib/ic/test/ic_SUITE_data/one_void.idl b/lib/ic/test/ic_SUITE_data/one_void.idl
new file mode 100644
index 0000000000..e1d51c7abb
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/one_void.idl
@@ -0,0 +1,30 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+// Test oneway operations not using in out params
+
+typedef long T;
+
+interface I1 {
+ oneway char op1(in char a);
+ oneway T op2(in char a);
+};
+
+
+
diff --git a/lib/ic/test/ic_SUITE_data/raises_reg.idl b/lib/ic/test/ic_SUITE_data/raises_reg.idl
new file mode 100644
index 0000000000..d4458811dc
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/raises_reg.idl
@@ -0,0 +1,52 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+#ifndef _RAISES_REG_IDL
+#define _RAISES_REG_IDL
+
+module Raises_RegModule {
+
+ exception Exception_1 {};
+
+ exception Exception_2 {};
+
+ interface R_R {
+
+ void op()
+ raises(Raises_RegModule::Exception_1,Raises_RegModule::Exception_2);
+
+ };
+
+};
+
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/ic/test/ic_SUITE_data/struct.idl b/lib/ic/test/ic_SUITE_data/struct.idl
new file mode 100644
index 0000000000..337ee170e3
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/struct.idl
@@ -0,0 +1,53 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+
+struct S1 {
+ long a;
+ char b;
+ string<9> s;
+};
+
+struct S2 {
+ long a;
+ struct S3 {
+ long a;
+ short b, b1;
+ char c;
+ } b;
+ sequence <S1> c, c2, c3, c4, c5, c6, c7;
+};
+
+
+// Check that structs are detected down in other types
+
+
+typedef struct s4 {long a;} T1;
+union U1 switch (long) {
+case 1:
+ struct S5 {unsigned short a;} a;
+case 2:
+ union U2 switch (char) {
+ case 'a':
+ boolean a;
+ case 'b':
+ struct s6 {long a; boolean b;} c;
+ } b;
+};
+
diff --git a/lib/ic/test/ic_SUITE_data/syntax1.idl b/lib/ic/test/ic_SUITE_data/syntax1.idl
new file mode 100644
index 0000000000..83c7de7943
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/syntax1.idl
@@ -0,0 +1,28 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+//
+// Check syntax errors
+//
+
+
+typedef long T1 _;
+
+
+
diff --git a/lib/ic/test/ic_SUITE_data/syntax2.idl b/lib/ic/test/ic_SUITE_data/syntax2.idl
new file mode 100644
index 0000000000..10498206c1
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/syntax2.idl
@@ -0,0 +1,27 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+struct S2 {
+ long a_arr[99];
+ struct S3 {
+ long a;_arr[99]
+ boolean b_arr[99];
+ } b;
+};
+
+
diff --git a/lib/ic/test/ic_SUITE_data/syntax3.idl b/lib/ic/test/ic_SUITE_data/syntax3.idl
new file mode 100644
index 0000000000..69ab6b9783
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/syntax3.idl
@@ -0,0 +1,20 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+typdef long T1;
+
diff --git a/lib/ic/test/ic_SUITE_data/syntax4.idl b/lib/ic/test/ic_SUITE_data/syntax4.idl
new file mode 100644
index 0000000000..077a251729
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/syntax4.idl
@@ -0,0 +1,23 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+union U1 switch (long) {
+case 1: long a;
+2: short b;
+};
+
diff --git a/lib/ic/test/ic_SUITE_data/syntax5.idl b/lib/ic/test/ic_SUITE_data/syntax5.idl
new file mode 100644
index 0000000000..10af9fc18c
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/syntax5.idl
@@ -0,0 +1,22 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+union U1 switch (enum E1 {kalle, sune}) {
+case kalle: long a;
+sune: short b;
+};
diff --git a/lib/ic/test/ic_SUITE_data/syntax6.idl b/lib/ic/test/ic_SUITE_data/syntax6.idl
new file mode 100644
index 0000000000..dc15704d94
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/syntax6.idl
@@ -0,0 +1,20 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+constant long c1 = 0;
diff --git a/lib/ic/test/ic_SUITE_data/type.idl b/lib/ic/test/ic_SUITE_data/type.idl
new file mode 100644
index 0000000000..67e1d502bd
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/type.idl
@@ -0,0 +1,190 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+//
+// Check all types in IDL
+//
+
+typedef long T01;
+typedef unsigned long T02;
+typedef short T03;
+typedef unsigned short T04;
+typedef float T05;
+typedef double T06;
+typedef char T07;
+typedef boolean T08;
+typedef octet T09;
+typedef any T10;
+typedef Object T11;
+typedef T01 T12;
+
+// Template types
+typedef sequence <long> T21;
+typedef sequence <unsigned long> T22;
+typedef sequence <short, 2> T23;
+typedef sequence <unsigned short, 6> T24;
+typedef sequence <float, 12> T25;
+typedef sequence <double> T26;
+typedef sequence <char, 1> T27;
+typedef sequence <boolean> T28;
+typedef sequence <octet, 9> T29;
+typedef sequence <any> T30;
+typedef sequence <Object,2 > T31;
+typedef sequence <T01> T32;
+typedef sequence <sequence <sequence <T32> > > T33;
+
+struct S1 {
+ long a;
+ boolean b;
+};
+
+struct S2 {
+ long a;
+ struct S3 {
+ long a;
+ boolean b;
+ } b;
+};
+
+union U1 switch (enum E1 {kalle1, sune1}) {
+case kalle1: long a;
+default: boolean b;
+case sune1: octet c;
+};
+
+union U2 switch (enum E2 {kalle2, sune2}) {
+case kalle2: long a;
+default: struct S4 { long a; short b;} b;
+case sune2: octet c;
+};
+
+// Typedefs of above types
+
+typedef struct S11 {
+ long a;
+ boolean b;
+} T41;
+
+typedef struct S21 {
+ long a;
+ struct S3 {
+ long a;
+ boolean b;
+ } b;
+} T42;
+
+typedef union U11 switch (enum E3 {kalle3, sune3}) {
+case kalle3: long a;
+default: boolean b;
+case sune3: octet c;
+} T43;
+
+typedef union U21 switch (enum E4 {kalle4, sune4}) {
+case kalle4: long a;
+default: struct S4 { long a; short b;} b;
+case sune4: octet c;
+} T44;
+
+
+
+
+// Array versions
+
+typedef long T01_arr[99];
+typedef unsigned long T02_arr[99];
+typedef short T03_arr[99];
+typedef unsigned short T04_arr[99];
+typedef float T05_arr[99];
+typedef double T06_arr[99];
+typedef char T07_arr[99];
+typedef boolean T08_arr[99];
+typedef octet T09_arr[99];
+typedef any T10_arr[99];
+typedef Object T11_arr[99];
+typedef T01 T12_arr[99];
+
+typedef sequence <long> T21_arr[99];
+typedef sequence <unsigned long> T22_arr[99];
+typedef sequence <short, 2> T23_arr[99];
+typedef sequence <unsigned short, 6> T24_arr[99];
+typedef sequence <float, 12> T25_arr[99];
+typedef sequence <double> T26_arr[99];
+typedef sequence <char, 1> T27_arr[99];
+typedef sequence <boolean> T28_arr[99];
+typedef sequence <octet, 9> T29_arr[99];
+typedef sequence <any> T30_arr[99];
+typedef sequence <Object,2 > T31_arr[99];
+typedef sequence <T01> T32_arr[99];
+typedef sequence <sequence <sequence <T32> > > T33_arr[99];
+
+struct S12 {
+ long a;
+ boolean b_arr[99];
+};
+
+struct S22 {
+ long a_arr[99];
+ struct S3 {
+ long a_arr[99];
+ boolean b_arr[99];
+ } b;
+};
+
+union U12 switch (enum E12 {kalle12, sune12}) {
+case kalle12: long a_arr[99];
+default: boolean b;
+case sune12: octet c;
+};
+
+union U22 switch (enum E22 {kalle22, sune22}) {
+case kalle22: long a;
+default: struct S4 { long a; short b;} b_arr[99];
+case sune22: octet c;
+};
+
+// Typedefs of above types
+
+typedef struct S13 {
+ long a_arr[99];
+ boolean b;
+} T41_arr[99];
+
+typedef struct S23 {
+ long a;
+ struct S3 {
+ long a;
+ boolean b_arr[99];
+ char c;
+ } b;
+} T42_arr[99];
+
+typedef union U13 switch (enum E13 {kalle13, sune13}) {
+case kalle13: long a;
+default: boolean b_arr[99];
+case sune13: octet c;
+} T43_arr[99];
+
+typedef union U23 switch (enum E23 {kalle23, sune23}) {
+case kalle23: long a_arr[99];
+default: struct S4 { long a; short b;} b_arr[99];
+case sune23: octet c_arr[99];
+} T44_arr[99];
+
+
+
diff --git a/lib/ic/test/ic_SUITE_data/typeid.idl b/lib/ic/test/ic_SUITE_data/typeid.idl
new file mode 100644
index 0000000000..6e99f4a50d
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/typeid.idl
@@ -0,0 +1,28 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+interface I1 {};
+
+module M1 { interface I1 {};};
+
+module M2 { module M1 { interface I1 {};};};
+
+module M3 { module M2 { module M1 { interface I1 {};};};};
+
+
diff --git a/lib/ic/test/ic_SUITE_data/u_case_mult.idl b/lib/ic/test/ic_SUITE_data/u_case_mult.idl
new file mode 100644
index 0000000000..3c30e144d8
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/u_case_mult.idl
@@ -0,0 +1,54 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+// Check that case labels are not duplicated
+
+union U1 switch (long) {
+case 1 : long a;
+case 1 : short b;
+};
+
+union U2 switch (char) {
+case 'c' : long a;
+case 'c' : short b;
+};
+
+union U2b switch (char) {
+case 'c' :
+case 'c' : long a;
+case 'e': long b;
+case 'c': long c;
+};
+
+union U3 switch (enum E1 {kalle, kula}) {
+case kula : long a;
+case kula : short b;
+};
+
+union U4 switch (boolean) {
+case TRUE : long a;
+case TRUE : short b;
+};
+
+union U5 switch (boolean) {
+case TRUE : long a;
+default: short p;
+default: short pp;
+};
+
diff --git a/lib/ic/test/ic_SUITE_data/u_default.idl b/lib/ic/test/ic_SUITE_data/u_default.idl
new file mode 100644
index 0000000000..e5d94a5e54
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/u_default.idl
@@ -0,0 +1,51 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+//
+// Checking that default labels are correct in TK
+//
+
+interface i1 {
+ union U1 switch (long) {
+ default: long a;
+ case 1: case 2: long b;
+ };
+
+ union U2 switch (long) {
+ case 0: default: long a;
+ case 1: case 2: long b;
+ };
+
+ union U3 switch (long) {
+ case -1: long aa;
+ case 0: default: long a;
+ case 1: case 2: long b;
+ };
+
+ union U4 switch (long) {
+ case -1: long aa;
+ case 0: long a;
+ case 1: case 2: long b;
+ };
+
+ U1 op0();
+ U2 op1();
+ U3 op2();
+ U4 op3();
+};
diff --git a/lib/ic/test/ic_SUITE_data/u_mult.idl b/lib/ic/test/ic_SUITE_data/u_mult.idl
new file mode 100644
index 0000000000..b916861eec
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/u_mult.idl
@@ -0,0 +1,61 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+
+// Check multiply defined declarators
+
+enum E2 {kal, kula, E1}; // legal, but used below
+
+// Now check that declarator a is multiply defined in all unions below
+union U0 switch (long) {
+case 0: long a;
+case 1: short a;
+};
+union U00 switch (char) {
+case 'c' : long a;
+case 'f' : char c;
+case 'b' : short a;
+};
+union U000 switch (boolean) {
+case TRUE: long a;
+case FALSE: short a;
+};
+union U0000 switch (E2) {
+case kal: long a;
+case kula: short a;
+};
+
+
+
+
+// Check that enum name duplication is found.
+
+union U1 switch (enum E1 {kalle, kula, E1}) {
+case E1 : long a; // legal
+case kalle : short E1; // illegal
+};
+
+
+// This is legal, but ended up here anyway
+
+union U2 switch(::E2) {
+case kal : long a;
+case kula : short b;
+default : boolean E1;
+};
diff --git a/lib/ic/test/ic_SUITE_data/u_norm.idl b/lib/ic/test/ic_SUITE_data/u_norm.idl
new file mode 100644
index 0000000000..e23796b8ca
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/u_norm.idl
@@ -0,0 +1,63 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+
+union U1 switch (long) {
+case 1: long a;
+case 2: case 3: short b;
+};
+
+
+union U2 switch (unsigned short) {
+case 10: boolean a;
+case 188: char b;
+default: string c;
+};
+
+
+union U3 switch (enum E1 {kalle, kula, boll}) {
+case kalle: long a;
+case kula: U2 b;
+};
+
+enum E2 {Cissi, Anders};
+
+union U4 switch (::E2) {
+case Cissi: U1 a;
+default: case Anders: unsigned long b;
+};
+
+union U5 switch(char) {
+case 'e': long a;
+case 'b': case 'f': char b;
+default: struct S {long a; boolean b;} c;
+};
+
+
+// Now check that references can be used as case values
+
+const long c1 = 9;
+const long c2 = 10;
+
+union U6 switch (long) {
+case c1: boolean a;
+case ::c2: boolean b;
+};
+
+
diff --git a/lib/ic/test/ic_SUITE_data/u_type.idl b/lib/ic/test/ic_SUITE_data/u_type.idl
new file mode 100644
index 0000000000..44e3326305
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/u_type.idl
@@ -0,0 +1,82 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+
+//
+// Check that case values match declared discriminator type
+//
+
+
+const long longC = 0;
+const short shortC = 0;
+const char charC = 'c';
+const string stringC = "Yacht";
+
+enum E1 {kalle, kula};
+
+union U1 switch (long) {
+case 'c' : long a;
+case TRUE : long b;
+case stringC : long d;
+case kalle : long f;
+};
+
+union U2 switch (unsigned long) {
+case 'c' : long a;
+case TRUE : long b;
+case stringC : long d;
+case kalle : long f;
+};
+
+union U3 switch (short) {
+case 'c' : long a;
+case TRUE : long b;
+case stringC : long d;
+case kalle : long f;
+};
+
+union U4 switch (unsigned short) {
+case 'c' : long a;
+case TRUE : long b;
+case stringC : long d;
+case kalle : long f;
+};
+
+union U5 switch (char) {
+case TRUE : long b;
+case stringC : long d;
+case shortC : long e;
+case kalle : long f;
+};
+
+
+union U6 switch (E1) {
+case 'c' : long a;
+case TRUE : long b;
+case stringC : long d;
+case shortC : long e;
+};
+
+union U7 switch (enum E2 {ja, nej, kanske}) {
+case 'c' : long a;
+case TRUE : long b;
+case stringC : long d;
+case shortC : long e;
+};
+
diff --git a/lib/ic/test/ic_SUITE_data/undef_id.idl b/lib/ic/test/ic_SUITE_data/undef_id.idl
new file mode 100644
index 0000000000..01a35c4ef8
--- /dev/null
+++ b/lib/ic/test/ic_SUITE_data/undef_id.idl
@@ -0,0 +1,63 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1997-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+//
+// Check that undefined ids are detected
+//
+
+typedef T7 T1;
+
+const char c1 = ::c0;
+const T01 c2 = 'h';
+const T7 c3 = 9;
+
+interface i1 {
+ T17 op();
+ long op2( in T7 a);
+ attribute T7 a1, a2;
+ readonly attribute T17 a3;
+};
+
+union U1 switch (long) {
+case 1: long a;
+case ::g : short b;
+};
+
+union U2 switch (enum E1 {kalle, kula}) {
+case kula1: long a;
+case kalle : short b;
+};
+
+union U3 switch (long) {
+case kula2: long a;
+case ::E3::kalle : short b;
+case ::E4::kalle : short c;
+};
+
+enum E2 {kalle2, kula2};
+
+union U4 switch (E2) {
+case kula1: long a;
+case kula1: long b;
+case c3: short c;
+};
+
+
+
+
diff --git a/lib/ic/test/ic_be_SUITE.erl b/lib/ic/test/ic_be_SUITE.erl
new file mode 100644
index 0000000000..e3caf7bdff
--- /dev/null
+++ b/lib/ic/test/ic_be_SUITE.erl
@@ -0,0 +1,69 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+%%%----------------------------------------------------------------------
+%%% Purpose : Test suite for the backends of the IDL compiler
+%%%----------------------------------------------------------------------
+
+-module(ic_be_SUITE).
+-include("test_server.hrl").
+
+
+-export([all/1,plain/1]).
+
+
+-define(OUT(X), filename:join([?config(priv_dir, Config), gen, to_list(X)])).
+
+
+%% Top of cases
+
+all(suite) -> [plain].
+
+
+
+plain(doc) ->
+ ["Checking code for the plain backend."];
+plain(suite) -> [];
+plain(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(slask),
+ File = filename:join(DataDir, plain),
+
+ ?line ok = ic:gen(File,stdopts(OutDir)++[{be,erl_plain}]),
+
+ ok.
+
+
+
+
+%%--------------------------------------------------------------------
+%%
+%% Utilities
+
+
+stdopts(OutDir) ->
+ [{outdir, OutDir}, {maxerrs, infinity}].
+
+
+
+
+
+to_list(X) when is_atom(X) -> atom_to_list(X);
+to_list(X) -> X.
+
diff --git a/lib/ic/test/ic_be_SUITE_data/plain.idl b/lib/ic/test/ic_be_SUITE_data/plain.idl
new file mode 100644
index 0000000000..ee0a995807
--- /dev/null
+++ b/lib/ic/test/ic_be_SUITE_data/plain.idl
@@ -0,0 +1,33 @@
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+module m {
+
+ struct s {
+ long x;
+ long y;
+ };
+
+ interface i {
+
+ void foo( in s a, out short b );
+
+ };
+
+};
+
diff --git a/lib/ic/test/ic_pp_SUITE.erl b/lib/ic/test/ic_pp_SUITE.erl
new file mode 100644
index 0000000000..d68242bf3a
--- /dev/null
+++ b/lib/ic/test/ic_pp_SUITE.erl
@@ -0,0 +1,647 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+%%----------------------------------------------------------------------
+%% Purpose : Test suite for the IDL preprocessor
+%%----------------------------------------------------------------------
+
+-module(ic_pp_SUITE).
+-include("test_server.hrl").
+
+
+
+%% Standard options to the ic compiler, NOTE unholy use of OutDir
+
+-define(OUT(X), filename:join([?config(priv_dir, Config), gen, to_list(X)])).
+-define(GCC, "g++").
+-define(GCC_VER, "2.95.3").
+
+-export([all/1]).
+-export([arg/1]).
+-export([arg_norm/1]).
+-export([cascade/1]).
+-export([cascade_norm/1]).
+-export([comment/1]).
+-export([comment_norm/1]).
+-export([concat/1]).
+-export([concat_norm/1]).
+-export([define/1]).
+-export([define_norm/1]).
+-export(['if'/1]).
+-export([if_norm/1]).
+-export([if_zero/1]).
+-export([misc/1]).
+-export([misc_norm/1]).
+-export([improp_nest_constr/1]).
+-export([improp_nest_constr_norm/1]).
+-export([inc/1]).
+-export([inc_norm/1]).
+-export([line/1]).
+-export([line_norm/1]).
+-export([nopara/1]).
+-export([nopara_norm/1]).
+-export([predef/1]).
+-export([predef_norm/1]).
+-export([predef_time/1]).
+-export([predef_time_norm/1]).
+-export([self_ref/1]).
+-export([self_ref_norm/1]).
+-export([separate/1]).
+-export([separate_norm/1]).
+-export([swallow_sc/1]).
+-export([swallow_sc_norm/1]).
+-export([unintended_grp/1]).
+-export([unintended_grp_norm/1]).
+-export([cases/0, init_all/1, finish_all/1]).
+
+
+all(doc) -> ["Preprocessing tests for IC"];
+all(suite) ->
+ {req, [], {conf, init_all, cases(), finish_all}}.
+
+init_all(Config) ->
+ if
+ is_list(Config) ->
+ case os:type() of
+ {win32, _} ->
+ {skipped, "Very unplesent to run on windows"};
+ _ ->
+ check_gcc(Config)
+ end;
+ true ->
+ exit("Config not a list")
+ end.
+
+check_gcc(Config) ->
+ case os:find_executable(?GCC) of
+ false ->
+ {skipped,
+ lists:flatten(io_lib:format("Can not run without ~s in path",
+ [?GCC]))};
+ _ ->
+ case trim(os:cmd(?GCC++" --version")) of
+ ?GCC_VER++[] ->
+ Config;
+ ?GCC_VER++[D|_] when is_integer(D), D>=$0, D=<$9 ->
+ fail_gcc(?GCC_VER++[D]);
+ ?GCC_VER++_ ->
+ Config;
+ Ver ->
+ fail_gcc(Ver)
+ end
+ end.
+
+fail_gcc(Ver) ->
+ {skipped, lists:flatten(io_lib:format("Need ~s v~s, not ~s",
+ [?GCC, ?GCC_VER, Ver]))}.
+
+trim(S) -> lists:reverse(skip_white(lists:reverse(skip_white(S)))).
+
+skip_white([$\s|T]) -> skip_white(T);
+skip_white([$\n|T]) -> skip_white(T);
+skip_white([$\r|T]) -> skip_white(T);
+skip_white([$\t|T]) -> skip_white(T);
+skip_white(L) -> L.
+
+
+finish_all(Config) ->
+ Config.
+
+
+cases() ->
+ [arg, cascade, comment, concat, define, misc, 'if', improp_nest_constr, inc,
+ line, nopara, predef, predef_time, self_ref, separate, swallow_sc,
+ unintended_grp].
+
+
+
+%%--------------------------------------------------------------------
+%% arg
+%%--------------------------------------------------------------------
+
+arg(suite) -> [arg_norm];
+arg(doc) -> ["Check #define with some arguments"].
+
+arg_norm(doc) -> ["Checks arguments for #define."];
+arg_norm(suite) -> [];
+arg_norm(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ _OutDir = ?OUT(arg_norm),
+ File = filename:join(DataDir, arg),
+
+ ?line ok = test_file(File, DataDir),
+ ok.
+
+
+%%--------------------------------------------------------------------
+%% cascade
+%%--------------------------------------------------------------------
+
+cascade(suite) -> [cascade_norm];
+cascade(doc) -> ["Check cascade #define"].
+
+cascade_norm(doc) -> ["Check cascade #define."];
+cascade_norm(suite) -> [];
+cascade_norm(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ _OutDir = ?OUT(cascade_norm),
+ File = filename:join(DataDir, cascade),
+
+ ?line ok = test_file(File, DataDir),
+ ok.
+
+
+%%--------------------------------------------------------------------
+%% comment
+%%--------------------------------------------------------------------
+
+comment(suite) -> [comment_norm];
+comment(doc) -> ["Check comments"].
+
+comment_norm(doc) -> ["Check comments."];
+comment_norm(suite) -> [];
+comment_norm(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ _OutDir = ?OUT(comment_norm),
+ File = filename:join(DataDir, comment),
+
+ ?line ok = test_file(File, DataDir),
+ ok.
+
+
+%%--------------------------------------------------------------------
+%% concat
+%%--------------------------------------------------------------------
+
+concat(suite) -> [concat_norm];
+concat(doc) -> ["Check concatinations, i.e ## "].
+
+concat_norm(doc) -> ["Check concatinations, i.e ## ."];
+concat_norm(suite) -> [];
+concat_norm(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ _OutDir = ?OUT(concat_norm),
+ File = filename:join(DataDir, concat),
+
+ ?line ok = test_file(File, DataDir),
+ ok.
+
+
+%%--------------------------------------------------------------------
+%% define
+%%--------------------------------------------------------------------
+
+define(suite) -> [define_norm];
+define(doc) -> ["Check misceleaneous #define"].
+
+define_norm(doc) -> ["Check misceleaneous #define."];
+define_norm(suite) -> [];
+define_norm(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ _OutDir = ?OUT(define_norm),
+ File = filename:join(DataDir, define),
+
+ ?line ok = test_file(File, DataDir),
+ ok.
+
+
+%%--------------------------------------------------------------------
+%% if
+%%--------------------------------------------------------------------
+
+'if'(suite) -> [if_norm, if_zero];
+'if'(doc) -> ["Check #if, #elif, and #endif. Note these are not implementen and will ~n
+ result in an error message from internal_pp"].
+
+if_norm(doc) -> ["Check #if, #elif, and #endif. ."];
+if_norm(suite) -> [];
+if_norm(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ _OutDir = ?OUT(if_norm),
+ File = filename:join(DataDir, 'if'),
+
+ ?line ok = test_file(File, DataDir),
+ ok.
+
+if_zero(doc) -> ["Check #if 0"];
+if_zero(suite) -> [];
+if_zero(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ _OutDir = ?OUT(if_zero),
+ File = filename:join(DataDir, if_zero),
+
+ ?line ok = test_file(File, DataDir),
+ ok.
+
+
+%%--------------------------------------------------------------------
+%% inc
+%%--------------------------------------------------------------------
+
+inc(suite) -> [inc_norm];
+inc(doc) -> ["Check #include"].
+
+inc_norm(doc) -> ["Check #include."];
+inc_norm(suite) -> [];
+inc_norm(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ _OutDir = ?OUT(inc_norm),
+ File = filename:join(DataDir, inc),
+
+ ?line ok = test_file(File, DataDir),
+ ok.
+
+
+
+%%--------------------------------------------------------------------
+%% improp_nest_constr
+%%--------------------------------------------------------------------
+
+improp_nest_constr(suite) -> [improp_nest_constr_norm];
+improp_nest_constr(doc) -> ["Check improperly nested constructs"].
+
+improp_nest_constr_norm(doc) -> ["Check improperly nested constructs."];
+improp_nest_constr_norm(suite) -> [];
+improp_nest_constr_norm(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ _OutDir = ?OUT(improp_nest_constr_norm),
+ File = filename:join(DataDir, improp_nest_constr),
+
+ ?line ok = test_file(File, DataDir),
+ ok.
+
+
+%%--------------------------------------------------------------------
+%% misc
+%%--------------------------------------------------------------------
+
+misc(suite) -> [misc_norm];
+misc(doc) -> ["Misceleaneous checks"].
+
+misc_norm(doc) -> ["Misceleaneous checks."];
+misc_norm(suite) -> [];
+misc_norm(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ _OutDir = ?OUT(misc_norm),
+ File = filename:join(DataDir, misc),
+
+ ?line ok = test_file(File, DataDir),
+ ok.
+
+
+%%--------------------------------------------------------------------
+%% line
+%%--------------------------------------------------------------------
+
+line(suite) -> [line_norm];
+line(doc) -> ["Checks #line"].
+
+line_norm(doc) -> ["Checks #line."];
+line_norm(suite) -> [];
+line_norm(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ _OutDir = ?OUT(line_norm),
+ File = filename:join(DataDir, line),
+
+ ?line ok = test_file(File, DataDir),
+ ok.
+
+
+%%--------------------------------------------------------------------
+%% nopara
+%%--------------------------------------------------------------------
+
+nopara(suite) -> [nopara_norm];
+nopara(doc) -> ["Checks #define with no parameters"].
+
+nopara_norm(doc) -> ["Checks #define with no parameters."];
+nopara_norm(suite) -> [];
+nopara_norm(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ _OutDir = ?OUT(nopara_norm),
+ File = filename:join(DataDir, nopara),
+
+ ?line ok = test_file(File, DataDir),
+ ok.
+
+
+%%--------------------------------------------------------------------
+%% predef
+%%--------------------------------------------------------------------
+
+predef(suite) -> [predef_norm];
+predef(doc) -> ["Checks predefined macros. Note: not __TIME__ and __DATE__"].
+
+predef_norm(doc) -> ["Checks predefined macros. Note: not __TIME__ and __DATE__."];
+predef_norm(suite) -> [];
+predef_norm(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ _OutDir = ?OUT(predef_norm),
+ File = filename:join(DataDir, predef),
+
+ ?line ok = test_file(File, DataDir),
+ ok.
+
+
+%%--------------------------------------------------------------------
+%% predef_time
+%%--------------------------------------------------------------------
+
+predef_time(suite) -> [predef_time_norm];
+predef_time(doc) -> ["Checks the predefined macros __TIME__ and __DATE__"].
+
+predef_time_norm(doc) -> ["Checks the predefined macros __TIME__ and __DATE__."];
+predef_time_norm(suite) -> [];
+predef_time_norm(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ _OutDir = ?OUT(predef_time_norm),
+ File = filename:join(DataDir, predef_time),
+
+ ?line ok = test_file(File, DataDir),
+ ok.
+
+
+%%--------------------------------------------------------------------
+%% self_ref
+%%--------------------------------------------------------------------
+
+self_ref(suite) -> [self_ref_norm];
+self_ref(doc) -> ["Checks self referring macros"].
+
+self_ref_norm(doc) -> ["Checks self referring macros."];
+self_ref_norm(suite) -> [];
+self_ref_norm(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ _OutDir = ?OUT(self_ref_norm),
+ File = filename:join(DataDir, self_ref),
+
+ ?line ok = test_file(File, DataDir),
+ ok.
+
+
+%%--------------------------------------------------------------------
+%% separate
+%%--------------------------------------------------------------------
+
+separate(suite) -> [separate_norm];
+separate(doc) -> ["Checks separete expansion of macro arguments"].
+
+separate_norm(doc) -> ["Checks separete expansion of macro arguments."];
+separate_norm(suite) -> [];
+separate_norm(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ _OutDir = ?OUT(separate_norm),
+ File = filename:join(DataDir, separate),
+
+ ?line ok = test_file(File, DataDir),
+ ok.
+
+
+%%--------------------------------------------------------------------
+%% swallow_sc
+%%--------------------------------------------------------------------
+
+swallow_sc(suite) -> [swallow_sc_norm];
+swallow_sc(doc) -> ["Checks swallowing an undesirable semicolon"].
+
+swallow_sc_norm(doc) -> ["Checks swallowing an undesirable semicolon."];
+swallow_sc_norm(suite) -> [];
+swallow_sc_norm(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ _OutDir = ?OUT(swallow_sc_norm),
+ File = filename:join(DataDir, swallow_sc),
+
+ ?line ok = test_file(File, DataDir),
+ ok.
+
+
+%%--------------------------------------------------------------------
+%% unintended_grp
+%%--------------------------------------------------------------------
+
+unintended_grp(suite) -> [unintended_grp_norm];
+unintended_grp(doc) -> ["Checks unintended grouping of arithmetic"].
+
+unintended_grp_norm(doc) -> ["Checks unintended grouping of arithmetic."];
+unintended_grp_norm(suite) -> [];
+unintended_grp_norm(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ _OutDir = ?OUT(unintended_grp_norm),
+ File = filename:join(DataDir, unintended_grp),
+
+ ?line ok = test_file(File, DataDir),
+ ok.
+
+
+
+
+
+test_file(FileT, DataDir) ->
+ case test_file_1(FileT, DataDir) of
+ ok -> ok;
+ Chars ->
+ io:put_chars(Chars),
+ {error,{FileT,DataDir}}
+ end.
+
+test_file_1(FileT, DataDir) ->
+ Tok = string:tokens(FileT, "/"),
+ FileName = lists:last(Tok),
+ File = FileT++".idl",
+
+ ?line test_server:format("File ~p~n",[File]),
+ ?line test_server:format("FileName ~p~n",[FileName]),
+
+ Flags = "-I"++DataDir,
+
+ ?line test_server:format("Flags ~p~n",[Flags]),
+
+ ?line Erl = pp_erl(File, Flags),
+ ?line Gcc = pp_gcc(File, Flags),
+
+ ?line case Erl of
+ {error,_ErlError} ->
+ ?line test_server:format("Internal_pp Result ~n==================~n~p~n~n",[Erl]);
+ {warning, _ErlWar} ->
+ ?line test_server:format("Internal_pp Result ~n==================~n~p~n~n",[Erl]);
+ _ ->
+ ?line test_server:format("Internal_pp Result ~n==================~n~s~n~n",[Erl])
+ end,
+
+ ?line case Gcc of
+ {error,GccError} ->
+ Error = string:tokens(GccError, "\n"),
+ ?line test_server:format(?GCC" Result ~n==========~n~p~n~n",
+ [Error]);
+ _ ->
+ ?line test_server:format(?GCC" Result ~n==========~n~s~n~n",[Gcc])
+ end,
+
+
+
+ ?line case {Erl,Gcc} of
+ {{warning,W}, {error,X}} ->
+ ?line case is_ok(W,X) of
+ yes ->
+ ok;
+ no ->
+ io_lib:format("Internal_pp found Warning = ~p ~n"
+ ?GCC" found Error = ~p~n",[W,X])
+ end;
+
+
+ {{warning,W}, _} ->
+ io_lib:format(?GCC" did not find warnings while ~n"
+ "Internal_pp found the following Warning = ~p~n",[W]);
+
+ {{error,E}, {error,X}} ->
+ ?line case is_ok(E,X) of
+ yes ->
+ ok;
+ no ->
+ io_lib:format("Internal_pp found Error = ~p ~n"
+ ?GCC" found Error = ~p~n",[E,X])
+ end;
+
+ {{error,E}, _} ->
+ ?line case FileName of
+ "if" ->
+ ?line case if_res(E) of
+ ok ->
+ ok;
+ _ ->
+ io_lib:format(?GCC" did not find errors while ~n"
+ "Internal_pp found the following Error = ~p~n",[E])
+ end;
+ _ ->
+ io_lib:format(?GCC" did not find errors while ~n"
+ "Internal_pp found the following Error = ~p~n",[lists:flatten(E)])
+ end;
+
+ {_, {error,X}} ->
+ io_lib:format("Internal_pp did not find errors while ~n"
+ ?GCC" found the following Error = ~p~n",[X]);
+
+ _ ->
+
+ ?line file:write_file("/tmp/Erl.pp",list_to_binary(Erl)),
+ ?line file:write_file("/tmp/Gcc.pp",list_to_binary(Gcc)),
+
+ ?line Res = os:cmd("diff -b -w /tmp/Erl.pp /tmp/Gcc.pp"),
+ ?line test_server:format("///////////{error,E} E ~p FileName~p~n",[Res,FileName]),
+ ?line case {Res, FileName} of
+ {[], _} ->
+ ?line test_server:format("Diff = [] OK!!!!!!~n"),
+ ok;
+ {_, "predef_time"} ->
+ Tokens = string:tokens(Res,"\n"),
+ ?line test_server:format("///////////{error,E} Tokens~p~n",[Tokens]),
+ case Tokens of
+ ["3c3",_,"---",_,"5c5",_,"---",_,"9c9",_,"---",_] ->
+ ok;
+ _ ->
+ io_lib:format("Diff Result = ~p~n",[Res])
+ end;
+ _ ->
+ io_lib:format("Diff Result = ~p~n",[Res])
+ end
+ end.
+
+
+
+
+
+pp_erl(File, Flags) ->
+ case ic_pp:run(File,Flags) of
+ {ok, [$#, $ , $1 | Rest], []} ->
+ [$#, $ , $1 | Rest];
+ {ok, [$#, $ , $1 | _Rest], Warning} ->
+ {warning,Warning};
+ {error,Error} ->
+ {error,Error}
+ end.
+
+pp_gcc(File, Flags) ->
+ Cmd = ?GCC" -x c++ -E",
+ Line = Cmd++" "++Flags++" "++File,
+
+ case os:cmd(Line) of
+ [$#, $ , $1 | Rest] ->
+ [$#, $ , $1 | Rest];
+ Res ->
+
+ case string:str(Res,"# 1 \"") of
+ 0 ->
+ {error,Res};
+ X ->
+ {error, string:sub_string(Res, 1, X-1)}
+ end
+ end.
+
+
+is_ok([],_Gcc) ->
+ yes;
+is_ok([{FileName,Line,Text}|T],Gcc) ->
+ Str = FileName++":"++integer_to_list(Line)++": "++Text,
+ case string:str(Gcc,Str) of
+ 0 ->
+ io:format("~n is_ok Internal_pp missed Error = ~s~n",[Str]),
+ no;
+ _X ->
+ is_ok(T,Gcc)
+ end;
+is_ok([Str|T],Gcc) ->
+ case string:str(Gcc,Str) of
+ 0 ->
+ io:format("~n is_ok Internal_pp missed Error = ~s~n",[Str]),
+ no;
+ _X ->
+ is_ok(T,Gcc)
+ end.
+
+
+to_list(X) when is_atom(X) -> atom_to_list(X);
+to_list(X) -> X.
+
+
+
+if_res(E) ->
+ if_res(E,1).
+
+if_res([H|T],Nr) ->
+ %% Dir = "/clearcase/otp/libraries/ic/test/ic_pp_SUITE_data/if.idl",
+ case {Nr, H} of
+ {1, {_Dir, 2, "only '#if 0' is implemented at present"}} ->
+ if_res(T,Nr+1);
+ {2, {_Dir, 3, "only '#if 0' is implemented at present"}} ->
+ if_res(T,Nr+1);
+ {3, {_Dir, 5, "`else' command is not implemented at present"}} ->
+ if_res(T,Nr+1);
+ {4, {_Dir, 9, "`elif' command is not implemented at present"}} ->
+ if_res(T,Nr+1);
+ {5, {_Dir, 11, "`else' command is not implemented at present"}} ->
+ ok;
+ _ ->
+ error
+ end;
+if_res(_, _) ->
+ error.
+
+
+
diff --git a/lib/ic/test/ic_pp_SUITE_data/arg.idl b/lib/ic/test/ic_pp_SUITE_data/arg.idl
new file mode 100644
index 0000000000..b4d266121d
--- /dev/null
+++ b/lib/ic/test/ic_pp_SUITE_data/arg.idl
@@ -0,0 +1,38 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+#define xstr (s) str(s)
+#define str(s) #s
+#define foo 4
+
+xstr(foo);
+
+#define x(kalle)stina
+x(kurt)
+x
+
+#define y(kalle) stina
+y(kurt)
+y
+
+#define a(kalle) stina
+a(kurt)
+a
+
+#define b (kalle) stina
+b(kurt)
diff --git a/lib/ic/test/ic_pp_SUITE_data/cascade.idl b/lib/ic/test/ic_pp_SUITE_data/cascade.idl
new file mode 100644
index 0000000000..8dff1ee99f
--- /dev/null
+++ b/lib/ic/test/ic_pp_SUITE_data/cascade.idl
@@ -0,0 +1,29 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+#define BUFS 1020
+#define TABS BUFS
+#undef BUFS
+#define BUFS 37
+
+
+main()
+{
+ TABS;
+
+}
diff --git a/lib/ic/test/ic_pp_SUITE_data/comment.idl b/lib/ic/test/ic_pp_SUITE_data/comment.idl
new file mode 100644
index 0000000000..d2ca3e7872
--- /dev/null
+++ b/lib/ic/test/ic_pp_SUITE_data/comment.idl
@@ -0,0 +1,72 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+#define T 12
+#define F T
+
+//comment
+/*exception except {};*/
+
+// comment
+ // comment
+/* another */
+ /* another */
+/* still
+another */
+ /* still
+ another */
+__LINE__
+/* yet \
+ another */
+// yet \
+ another
+__LINE__
+
+#include "all.c"
+#include <all.c>
+#include /* comment */ "all.c"
+#include /* comment */ <all.c>
+#include "all.c" /* comment */
+#include <all.c> /* comment */
+#include // "all.c"
+#include // <all.c>
+#include "all.c" // comment
+#include <all.c> // comment
+#include "all/*cc*/.c"
+#include <all/*cc*/.c>
+
+main()
+{
+ printf(" %d \n",F);
+ a();
+
+}
+//comment
+/*exception hell {};*/
+#undef T
+#define T "3/*com\
+ment*/4"
+a()
+{
+ printf(" %d \n",F);
+ printf(" %d \n",T);
+}
+
+b()
+{}
+
diff --git a/lib/ic/test/ic_pp_SUITE_data/concat.idl b/lib/ic/test/ic_pp_SUITE_data/concat.idl
new file mode 100644
index 0000000000..b8527fadfc
--- /dev/null
+++ b/lib/ic/test/ic_pp_SUITE_data/concat.idl
@@ -0,0 +1,60 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+#define sune kurt
+#define a(name) a #name name##_command
+#define b(name) b #name name## _command
+#define c(name) c #name name ##_command
+#define d(name) d #name name ## _command
+#define e(name) e #name command ## _command
+#define f(name) f #name command ## %_command
+#define g(name) g #name name ## %_command
+#define h(name) h #name %_command ## name
+#define i(name) i #name name ## _ ## name
+#define j(name) j #name name ## name
+#define k(name) k #name name ## name
+#define l(name) l #name !name ## name
+#define m(name) m #name name ## !name
+#define n(name) n #name !name ## !name
+#define o(name) stina
+#define p(name) name
+#define q1(name) q1 #name j(name) ## j(name)
+#define q2(name) q2 #name j(name)
+#define q3(name) q3 #name !! ## j(name)
+#define q4(name) q4 #name ## j(name)
+
+a(quit)
+b(quit)
+c(quit)
+d(quit)
+e(quit)
+f(quit)
+g(sune)
+h(sune)
+i(sune)
+j(sune)
+l(sune)
+m(sune)
+n(sune)
+k(j(sune))
+k(o(sune))
+k(p(sune))
+q1(sune)
+q2(sune)
+q3(sune)
+q4(sune)
diff --git a/lib/ic/test/ic_pp_SUITE_data/define.idl b/lib/ic/test/ic_pp_SUITE_data/define.idl
new file mode 100644
index 0000000000..6aac63dd1e
--- /dev/null
+++ b/lib/ic/test/ic_pp_SUITE_data/define.idl
@@ -0,0 +1,41 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+#define 8
+#define
+#define a
+#define _a
+#define b dfs
+#define 9 fdas
+#define a8
+#define A
+#define (c) fadfas
+#define )c) fadfas
+#define % c) fadfas
+#define d(p) kfdsa
+#define e(p) sinus(p)
+#warning warning line
+#define w%er percent
+#define q() no_para
+#warning warning line
+#undef
+#undef 8
+#undef a
+#undef b
+#undef _a d(kk)
+
diff --git a/lib/ic/test/ic_pp_SUITE_data/if.idl b/lib/ic/test/ic_pp_SUITE_data/if.idl
new file mode 100644
index 0000000000..c381fa73ee
--- /dev/null
+++ b/lib/ic/test/ic_pp_SUITE_data/if.idl
@@ -0,0 +1,32 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+#define kurt 12
+#if !true
+#if X == 1
+ett
+#else
+else
+#endif
+true
+#elif kurt
+trueelif
+#else
+trueelse
+#endif
+end
diff --git a/lib/ic/test/ic_pp_SUITE_data/if_zero.idl b/lib/ic/test/ic_pp_SUITE_data/if_zero.idl
new file mode 100644
index 0000000000..d715f9d61e
--- /dev/null
+++ b/lib/ic/test/ic_pp_SUITE_data/if_zero.idl
@@ -0,0 +1,31 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+#if 0
+pelle = mallan
+#endif
+pelle = stina
+#if 0
+kalle = stina
+#endif
+kalle = mallan
+#if 0
+kurt = fia
+#endif
+fia = kurt
+
diff --git a/lib/ic/test/ic_pp_SUITE_data/improp_nest_constr.idl b/lib/ic/test/ic_pp_SUITE_data/improp_nest_constr.idl
new file mode 100644
index 0000000000..463ee3c695
--- /dev/null
+++ b/lib/ic/test/ic_pp_SUITE_data/improp_nest_constr.idl
@@ -0,0 +1,30 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+#define double(x) (2*(x))
+#define call_with_1(x) x(1)
+
+#define strange(file) fprintf (file, "%s %d",
+
+main()
+{
+ call_with_1(double);
+ strange(stderr) p, 35)
+
+}
+
diff --git a/lib/ic/test/ic_pp_SUITE_data/inc.idl b/lib/ic/test/ic_pp_SUITE_data/inc.idl
new file mode 100644
index 0000000000..0dcd637082
--- /dev/null
+++ b/lib/ic/test/ic_pp_SUITE_data/inc.idl
@@ -0,0 +1,68 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+int x;
+
+#include "head.h"
+#warning line nr
+main()
+{
+ printf(test());
+}
+
+
+
+
+
+
+
+
+#define C false
+#define Z on
+#include "inc2.h"
+#undef Z
+"Ca" C
+"Za" Z
+#include "inc2.h"
+"Cb" C
+"Zb" Z
+
+main()
+{
+#define Q(a,b) sinus(a,b kurt ## b)
+ if (Q(34,56)=='NULL') printf(" T AAA%sEEEE \n",Q);
+ printf(" %d \n",F);
+ a();
+}
+//comment
+/*exception
+hell {};*/
+#undef T
+#define T "3/*com\ment*/4"
+#define T 33
+#define F again
+a ()
+{
+ printf(" %d \n",F);
+ printf(" %d \n",T);
+}
+
+b()
+{}
+
diff --git a/lib/ic/test/ic_pp_SUITE_data/included1.idl b/lib/ic/test/ic_pp_SUITE_data/included1.idl
new file mode 100644
index 0000000000..4cd26c4543
--- /dev/null
+++ b/lib/ic/test/ic_pp_SUITE_data/included1.idl
@@ -0,0 +1,35 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 2000-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+#ifndef INCLUDED1_IDL
+#define INCLUDED1_IDL
+
+
+#ifndef SOMETHING
+#endif
+
+
+struct s {
+
+ long l;
+
+};
+
+
+
+#endif
diff --git a/lib/ic/test/ic_pp_SUITE_data/included2.idl b/lib/ic/test/ic_pp_SUITE_data/included2.idl
new file mode 100644
index 0000000000..7cc44eef3e
--- /dev/null
+++ b/lib/ic/test/ic_pp_SUITE_data/included2.idl
@@ -0,0 +1,41 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 2000-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+#ifndef INCLUDED2_IDL
+#define INCLUDED2_IDL
+
+#include "included1.idl"
+
+
+#ifdef SOMETHING
+#endif
+
+
+module m {
+
+ struct t {
+
+ s st;
+
+ };
+
+
+};
+
+
+#endif
diff --git a/lib/ic/test/ic_pp_SUITE_data/includer.idl b/lib/ic/test/ic_pp_SUITE_data/includer.idl
new file mode 100644
index 0000000000..c6ebc234e8
--- /dev/null
+++ b/lib/ic/test/ic_pp_SUITE_data/includer.idl
@@ -0,0 +1,45 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 2000-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+#ifndef INCLUDER_IDL
+#define INCLUDER_IDL
+
+#include "included1.idl"
+#include "included2.idl"
+
+#ifdef SOMETHING
+#endif
+
+
+
+module n {
+
+ interface j {
+
+ s op(in m::t inpar);
+
+ };
+
+};
+
+
+
+
+#endif
+
+
diff --git a/lib/ic/test/ic_pp_SUITE_data/line.idl b/lib/ic/test/ic_pp_SUITE_data/line.idl
new file mode 100644
index 0000000000..5bd9c9446d
--- /dev/null
+++ b/lib/ic/test/ic_pp_SUITE_data/line.idl
@@ -0,0 +1,45 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+#line
+#line 8
+#line 8a
+#line 12 abc.c
+#line 12 "kurt.c"
+#warning fdafdsaf
+
+
+#define T 12
+#define F T
+#define Q(a) sinus(a)
+#undef Q
+#
+#line 12
+#warning test of warning
+#warning second of warning
+#warning third of warning
+#pragma kurt
+#ident kurt
+#kurt fdsafd
+#line 20
+main()
+{
+ if (Q(34,56)=='NULL') printf(" T AAA%sEEEE \n",Q);
+ printf(" %d \n",F);
+}
+sune
diff --git a/lib/ic/test/ic_pp_SUITE_data/misc.idl b/lib/ic/test/ic_pp_SUITE_data/misc.idl
new file mode 100644
index 0000000000..9c18610fcf
--- /dev/null
+++ b/lib/ic/test/ic_pp_SUITE_data/misc.idl
@@ -0,0 +1,44 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+#define str(s) #s
+str(fool);
+str(foo);
+str(kurt);
+#define xstr(s) str(s)
+#define foo 4
+#define kurt sune
+#define sune 17
+
+xstr(fool);
+xstr(foo);
+xstr(kurt);
+
+#define a(b) b #8b
+#define r(b) b #
+#define t(b) b ## a
+a(sinus)
+
+#define ww #www
+ww
+
+#define x 14 + y
+#define y 12 + #x
+x
+
+#define e(a) cosinus(a)
diff --git a/lib/ic/test/ic_pp_SUITE_data/nopara.idl b/lib/ic/test/ic_pp_SUITE_data/nopara.idl
new file mode 100644
index 0000000000..1bb137da11
--- /dev/null
+++ b/lib/ic/test/ic_pp_SUITE_data/nopara.idl
@@ -0,0 +1,35 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+#11a
+#define xstr str(s) + kurt*2;
+#define asdf pragma
+#asdf
+#define asd #pragma asd
+
+#10
+#12 8kurt
+
+#define sss "stringing in the rain"
+#define ddd "string
+ing in the rain" asd
+#line 20
+#include "head.h" qqqq
+#include %!#
+#include <sys.h>
+
diff --git a/lib/ic/test/ic_pp_SUITE_data/predef.idl b/lib/ic/test/ic_pp_SUITE_data/predef.idl
new file mode 100644
index 0000000000..d8abcb25d5
--- /dev/null
+++ b/lib/ic/test/ic_pp_SUITE_data/predef.idl
@@ -0,0 +1,33 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+#define b(q,w) kurt q w
+
+
+b(__LINE__, __FILE__)
+__LINE__
+__FILE__
+
+
+
+b(__INCLUDE_LEVEL__, __BASE_FILE__)
+__INCLUDE_LEVEL__
+__BASE_FILE__
+
+Line __LINE__
+#include "predef.h"
diff --git a/lib/ic/test/ic_pp_SUITE_data/predef_time.idl b/lib/ic/test/ic_pp_SUITE_data/predef_time.idl
new file mode 100644
index 0000000000..05e3ba9175
--- /dev/null
+++ b/lib/ic/test/ic_pp_SUITE_data/predef_time.idl
@@ -0,0 +1,24 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+#define b(q,w) kurt q w
+b(__DATE__, __TIME__)
+__DATE__
+__TIME__
+
+#include "predef_time.h"
diff --git a/lib/ic/test/ic_pp_SUITE_data/self_ref.idl b/lib/ic/test/ic_pp_SUITE_data/self_ref.idl
new file mode 100644
index 0000000000..a44666272e
--- /dev/null
+++ b/lib/ic/test/ic_pp_SUITE_data/self_ref.idl
@@ -0,0 +1,26 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+#define foo (4 + foo)
+
+
+main()
+{
+ foo;
+
+}
diff --git a/lib/ic/test/ic_pp_SUITE_data/separate.idl b/lib/ic/test/ic_pp_SUITE_data/separate.idl
new file mode 100644
index 0000000000..a3faf9b986
--- /dev/null
+++ b/lib/ic/test/ic_pp_SUITE_data/separate.idl
@@ -0,0 +1,37 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+#define xstr(s) str(s)
+#define str(s) #s
+#define foo 4
+#define str1(s) #s lose(s)
+#define foo1 4
+
+main()
+{
+ str(foo);
+ str1(foo1);
+ xstr(foo);
+
+#define qxstr(s) qstr(s)
+ qxstr(qfoo);
+#define qstr(s) #s
+ qstr( 4 ) ;
+#define qfoo 4
+ qstr(qfoo);
+}
diff --git a/lib/ic/test/ic_pp_SUITE_data/swallow_sc.idl b/lib/ic/test/ic_pp_SUITE_data/swallow_sc.idl
new file mode 100644
index 0000000000..71ed329ca6
--- /dev/null
+++ b/lib/ic/test/ic_pp_SUITE_data/swallow_sc.idl
@@ -0,0 +1,37 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+/* comment \
+ ends */
+// comment\
+ends
+Line __LINE__
+#define SKIP_SPACES(p, limit) \
+{register char *lim = (limit); \
+ while (p != lim) { \
+ if (*p++ != ' ') { \
+ p--; break; }}}
+
+
+main()
+{
+ if (*p != 0)
+ SKIP_SPACES (ppp, lim);
+ else
+ a = 17;
+}
diff --git a/lib/ic/test/ic_pp_SUITE_data/unintended_grp.idl b/lib/ic/test/ic_pp_SUITE_data/unintended_grp.idl
new file mode 100644
index 0000000000..3618bab1bc
--- /dev/null
+++ b/lib/ic/test/ic_pp_SUITE_data/unintended_grp.idl
@@ -0,0 +1,29 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+#define ceil_div( xz, yz) (xz + yz - 1) / yz
+#define ceil_div2(xz, yz) ((xz) + (yz) - 1) / (yz)
+
+#define b kurt
+
+main()
+{
+ ceil_div(b & c, sizeof(int));
+ ceil_div2(b & c, sizeof(int));
+
+}
diff --git a/lib/ic/test/ic_pragma_SUITE.erl b/lib/ic/test/ic_pragma_SUITE.erl
new file mode 100644
index 0000000000..0edb5d4717
--- /dev/null
+++ b/lib/ic/test/ic_pragma_SUITE.erl
@@ -0,0 +1,295 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+%%-----------------------------------------------------------------
+%% File: ic_pragma_SUITE.erl
+%%
+%% Description:
+%% Test suite for the IFR object registration when
+%% pragmas are engaged
+%%
+%%-----------------------------------------------------------------
+-module(ic_pragma_SUITE).
+
+-include("test_server.hrl").
+-include_lib("orber/include/corba.hrl").
+%%-----------------------------------------------------------------
+%% External exports
+%%-----------------------------------------------------------------
+-export([all/1, init_all/1, finish_all/1]).
+-export([ifr_pragma_reg/1, pragma_error/1, uggly_pragmas/1]).
+
+
+%%-----------------------------------------------------------------
+%% Macros
+%%-----------------------------------------------------------------
+-define(REMAP_EXCEPT(F), case catch F of
+ {'EXCEPTION', E} -> exit(E);
+ R -> R
+ end).
+%% Standard options to the ic compiler, NOTE unholy use of OutDir
+
+-define(OUT(X), filename:join([?config(priv_dir, Config), gen, to_list(X)])).
+
+
+%%-----------------------------------------------------------------
+%% Func: all/1
+%% Args:
+%% Returns:
+%%-----------------------------------------------------------------
+all(doc) -> ["Description", "more description"];
+all(suite) -> {req,
+ [mnesia],
+ {conf, init_all, cases(), finish_all}}.
+
+cases() ->
+ [ifr_pragma_reg,pragma_error,uggly_pragmas].
+
+%%-----------------------------------------------------------------
+%% Init and cleanup functions.
+%%-----------------------------------------------------------------
+init_all(Config) ->
+ io:format("Setting up.....~n"),
+ mnesia:stop(),
+ mnesia:delete_schema([node()]),
+ mnesia:create_schema([node()]),
+ mnesia:start(),
+ orber:install([node()]),
+ orber:start(),
+ if
+ is_list(Config) ->
+ Config;
+ true ->
+ exit("Config not a list")
+ end.
+
+finish_all(Config) ->
+ io:format("Setting down.....~n"),
+ orber:stop(),
+ orber:uninstall(),
+ mnesia:stop(),
+ mnesia:delete_schema([node()]),
+ Config.
+
+
+
+
+%%-----------------------------------------------------------------
+%% Test Case: IFR registration with pragmas
+%%-----------------------------------------------------------------
+ifr_pragma_reg(doc) ->
+ ["Checks that IFR object is correctly registered under pragma engagement."];
+ifr_pragma_reg(suite) -> [];
+ifr_pragma_reg(Config) when is_list(Config) ->
+ ?REMAP_EXCEPT(ifr_pragma_reg_run(Config)).
+
+ifr_pragma_reg_run(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(ifr_pragma_reg),
+ File0 = filename:join(DataDir, reg_m0),
+ ?line ok = ic:gen(File0, stdopts(OutDir)++[{preproc_flags,
+ "-I" ++ DataDir}]),
+ ?line ok = compile(OutDir, ifr_pragma_files()),
+ code:add_pathz(OutDir),
+
+ %% OE_register for all files
+ ?line ok = 'oe_reg_m0':'oe_register'(),
+
+ %% Pragma registration test
+ OE_IFR = orber_ifr:find_repository(),
+ io:format("~n##### Starting the test case #####~n"),
+ check_pragma_effect(OE_IFR,"IDL:M1/T1:1.0"),
+ check_pragma_effect(OE_IFR,"DCE:d62207a2-011e-11ce-88b4-0800090b5d3e:3"),
+ check_pragma_effect(OE_IFR,"IDL:P2/T3:1.0"),
+ check_pragma_effect(OE_IFR,"IDL:P1/M2/T4:2.4"),
+
+ %% OE_unregister for all files
+ ?line ok = 'oe_reg_m0':'oe_unregister'(),
+ code:del_path(OutDir),
+ ok.
+
+
+ifr_pragma_files() -> ['oe_reg_m0'].
+
+
+check_pragma_effect(OE_IFR,ID) ->
+ io:format("Checking for existance of : ~s~n",[ID]),
+ case orber_ifr:lookup_id(OE_IFR,ID) of
+ [] ->
+ test_server:fail(ID ++ " does not exist"),
+ false;
+ {Def,_} ->
+ io:format("Id refers to = {~p,#Bin}~n",[Def]),
+ true
+ end.
+
+
+
+
+%%-----------------------------------------------------------------
+%% Test Case: Syntactical / Semantical error pragma definitions
+%%-----------------------------------------------------------------
+pragma_error(doc) ->
+ ["Finds errornous pragma definitions under compilation."];
+pragma_error(suite) -> [];
+pragma_error(Config) when is_list(Config) ->
+ ?REMAP_EXCEPT(pragma_error_run(Config)).
+
+pragma_error_run(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(pragma_error),
+ File1 = filename:join(DataDir, reg_m1),
+ File2 = filename:join(DataDir, reg_m2),
+ File3 = filename:join(DataDir, reg_m3),
+ File4 = filename:join(DataDir, reg_m4),
+ File5 = filename:join(DataDir, reg_m5),
+ File6 = filename:join(DataDir, reg_m6),
+
+ ?line error = ic:gen(File1, stdopts(OutDir)++[{preproc_flags,
+ "-I" ++ DataDir}] ),
+
+ ?line error = ic:gen(File2, stdopts(OutDir)++[{preproc_flags,
+ "-I" ++ DataDir}] ),
+
+ ?line error = ic:gen(File3, stdopts(OutDir)++[{preproc_flags,
+ "-I" ++ DataDir}] ),
+
+ ?line ok = ic:gen(File4, stdopts(OutDir)++[{preproc_flags,
+ "-I" ++ DataDir}] ),
+
+ ?line error = ic:gen(File5, stdopts(OutDir)++[{preproc_flags,
+ "-I" ++ DataDir}] ),
+
+ ?line error = ic:gen(File6, stdopts(OutDir)++[{preproc_flags,
+ "-I" ++ DataDir}] ),
+ ok.
+
+
+
+
+%%-----------------------------------------------------------------
+%% Test Case: IFR registration with realy uggly placed pragmas
+%%-----------------------------------------------------------------
+uggly_pragmas(doc) ->
+ ["Checks that IFR object is correctly registered under really uggly pragma engagement."];
+uggly_pragmas(suite) -> [];
+uggly_pragmas(Config) when is_list(Config) ->
+ ?REMAP_EXCEPT(uggly_pragmas_run(Config)).
+
+uggly_pragmas_run(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(ifr_pragma_reg),
+ File0 = filename:join(DataDir, uggly),
+
+ ?line ok = ic:gen(File0, stdopts(OutDir)++[{preproc_flags,
+ "-I" ++ DataDir}]),
+
+ ?line ok = compile(OutDir, uggly_pragma_files()),
+ code:add_pathz(OutDir),
+
+ %% OE_register for all files
+ ?line ok = 'oe_uggly':'oe_register'(),
+
+ %% Pragma registration test
+ OE_IFR = orber_ifr:find_repository(),
+ io:format("~n##### Starting the test case #####~n"),
+
+ check_pragma_effect(OE_IFR, "IDL:M:1.0"),
+ check_pragma_effect(OE_IFR, "LOCAL:SomeLocalId:10"),
+ check_pragma_effect(OE_IFR, "LOCAL:SomeLocalId:11"),
+ check_pragma_effect(OE_IFR, "LOCAL:SomeLocalId:17"),
+ check_pragma_effect(OE_IFR, "LOCAL:SomeLocalId:34"),
+ check_pragma_effect(OE_IFR, "IDL:Exc1:2.2"),
+ check_pragma_effect(OE_IFR, "IDL:Exc2:2.2"),
+ check_pragma_effect(OE_IFR, "IDL:S:1.0"),
+ check_pragma_effect(OE_IFR, "IDL:U:1.0"),
+ check_pragma_effect(OE_IFR, "LOCAL:SomeLocalId:23"),
+
+ %% OE_unregister for all files
+ ?line ok = 'oe_uggly':'oe_unregister'(),
+
+ code:del_path(OutDir),
+ ok.
+
+
+uggly_pragma_files() -> ['oe_uggly'].
+
+
+
+
+%%----------------------------
+
+
+stdopts(OutDir) ->
+ [{outdir, OutDir}, {maxerrs, infinity}].
+
+
+compile(Dir, Files) ->
+ compile(Dir, Files, []).
+
+compile(Dir, Files, Opts) ->
+ {ok, Cwd} = file:get_cwd(),
+ file:set_cwd(Dir),
+ io:format("Changing to ~p~n", [Dir]),
+ case catch do_compile(Files, Opts) of
+ ok ->
+ file:set_cwd(Cwd);
+ Err ->
+ file:set_cwd(Cwd),
+ test_server:fail(Err)
+ end.
+
+do_compile([], _Opts) -> ok;
+do_compile([F | Fs], Opts) ->
+ io:format("Compiling ~p", [F]),
+ case compile:file(F, Opts) of
+ ok ->
+ io:format(" ok~n", []),
+ do_load(F, Opts),
+ do_compile(Fs, Opts);
+ {ok, _} ->
+ io:format(" ok~n", []),
+ do_load(F, Opts),
+ do_compile(Fs, Opts);
+ {ok, _, _} ->
+ io:format(" ok~n", []),
+ do_load(F, Opts),
+ do_compile(Fs, Opts);
+ Err ->
+ io:format(" error: ~p~n", [Err]),
+ Err
+ end.
+
+do_load(File, Opts) ->
+ case lists:member(load, Opts) of
+ true ->
+ io:format("Loading file ~p", [File]),
+ code:purge(File),
+ R = code:load_abs(File),
+ io:format("Loaded: ~p", [R]);
+ false ->
+ ok
+ end.
+
+
+to_list(X) when is_atom(X) -> atom_to_list(X);
+to_list(X) -> X.
+
+
+
diff --git a/lib/ic/test/ic_pragma_SUITE_data/reg_m0.idl b/lib/ic/test/ic_pragma_SUITE_data/reg_m0.idl
new file mode 100644
index 0000000000..80f0f2cdd1
--- /dev/null
+++ b/lib/ic/test/ic_pragma_SUITE_data/reg_m0.idl
@@ -0,0 +1,77 @@
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+// Normal pragmas
+
+module M1 {
+
+ typedef long T1;
+
+ typedef long T2;
+
+#pragma ID T2 "DCE:d62207a2-011e-11ce-88b4-0800090b5d3e:3"
+
+};
+
+
+#pragma prefix "P1"
+
+module M2 {
+
+ module M3 {
+
+#pragma prefix "P2"
+
+ interface I1 {
+ void Op( in short b,
+ out short c);
+ };
+ typedef long T3;
+ };
+
+
+ typedef long T4;
+
+#pragma version T4 2.4
+
+};
+
+
+
+/*
+
+ Specified types with the following scoped names
+ and RepositoryIds
+
+ ::M1::T1 IDL:M1/T1:1.0
+
+ ::M1::T2 DCE:d62207a2-011e-11ce-88b4-0800090b5d3e:3
+
+ ::M2::M3::T3 IDL:P2/T3:1.0
+
+ ::M2::T4 IDL:P1/M2/T4:2.4
+
+*/
+
+
+
+
+
+
+
+
diff --git a/lib/ic/test/ic_pragma_SUITE_data/reg_m1.idl b/lib/ic/test/ic_pragma_SUITE_data/reg_m1.idl
new file mode 100644
index 0000000000..6c22788290
--- /dev/null
+++ b/lib/ic/test/ic_pragma_SUITE_data/reg_m1.idl
@@ -0,0 +1,75 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+// Bad pragma IDs
+
+// Completelly bad id
+module M1 {
+
+ typedef long T1;
+
+ typedef long T2;
+
+#pragma ID T2 "CompletelyBadId"
+
+};
+
+
+// Bad id, should start with DCE
+module M2 {
+
+ typedef long T1;
+
+ typedef long T2;
+
+#pragma ID T2 "BAD:d62207a2-011e-11ce-88b4-0800090b5d3e:3"
+
+};
+
+
+// Bad version in ID : not a short number
+module M3 {
+
+ typedef long T1;
+
+ typedef long T2;
+
+#pragma ID T2 "DCE:d62207a2-011e-11ce-88b4-0800090b5d3e:ABCD"
+
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/ic/test/ic_pragma_SUITE_data/reg_m2.idl b/lib/ic/test/ic_pragma_SUITE_data/reg_m2.idl
new file mode 100644
index 0000000000..1751751295
--- /dev/null
+++ b/lib/ic/test/ic_pragma_SUITE_data/reg_m2.idl
@@ -0,0 +1,40 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+// Bad pragma versions
+
+
+// Bad major version : not a short number
+module M1 {
+
+ typedef long T4;
+
+#pragma version T4 2000000000.4
+
+};
+
+// Bad minor version : not a short number
+module M2 {
+
+ typedef long T4;
+
+#pragma version T4 2.4000000000000
+
+};
+
+
diff --git a/lib/ic/test/ic_pragma_SUITE_data/reg_m3.idl b/lib/ic/test/ic_pragma_SUITE_data/reg_m3.idl
new file mode 100644
index 0000000000..b7c9da249f
--- /dev/null
+++ b/lib/ic/test/ic_pragma_SUITE_data/reg_m3.idl
@@ -0,0 +1,38 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+// Bad pragma prefixs
+
+module M2 {
+
+ module M3 {
+
+#pragma prefix P2 // Should be "P2"
+
+ interface I1 {
+ void foo( in short b,
+ out short c);
+ };
+ typedef long T3;
+ };
+
+
+ typedef long T4;
+};
+
+
diff --git a/lib/ic/test/ic_pragma_SUITE_data/reg_m4.idl b/lib/ic/test/ic_pragma_SUITE_data/reg_m4.idl
new file mode 100644
index 0000000000..0c7079e3dd
--- /dev/null
+++ b/lib/ic/test/ic_pragma_SUITE_data/reg_m4.idl
@@ -0,0 +1,64 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+// Unrecognmizable pragmas
+
+module M1 {
+
+ typedef long T1;
+
+ typedef long T2;
+
+
+ // Should be ID directive
+
+#pragma ShouldBeId T2 "DCE:d62207a2-011e-11ce-88b4-0800090b5d3e:3"
+
+};
+
+ // Should be prefix directive
+
+#pragma ShouldBePrefix "P1"
+
+module M2 {
+
+ module M3 {
+
+ // Should be prefix directive
+
+#pragma ShouldBePrefix "P2"
+
+ interface I1 {
+ void foo( in short b,
+ out short c);
+ };
+ typedef long T3;
+ };
+
+
+ typedef long T4;
+
+
+ // Should be version
+
+#pragma ShouldBeVersion T4 2.4
+
+};
+
+
+
diff --git a/lib/ic/test/ic_pragma_SUITE_data/reg_m5.idl b/lib/ic/test/ic_pragma_SUITE_data/reg_m5.idl
new file mode 100644
index 0000000000..cbf053fac4
--- /dev/null
+++ b/lib/ic/test/ic_pragma_SUITE_data/reg_m5.idl
@@ -0,0 +1,28 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+// Version not in valid form : major.ninor
+
+module M1 {
+
+ typedef long T4;
+
+ #pragma version T4 2
+
+};
diff --git a/lib/ic/test/ic_pragma_SUITE_data/reg_m6.idl b/lib/ic/test/ic_pragma_SUITE_data/reg_m6.idl
new file mode 100644
index 0000000000..b7c9da249f
--- /dev/null
+++ b/lib/ic/test/ic_pragma_SUITE_data/reg_m6.idl
@@ -0,0 +1,38 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+// Bad pragma prefixs
+
+module M2 {
+
+ module M3 {
+
+#pragma prefix P2 // Should be "P2"
+
+ interface I1 {
+ void foo( in short b,
+ out short c);
+ };
+ typedef long T3;
+ };
+
+
+ typedef long T4;
+};
+
+
diff --git a/lib/ic/test/ic_pragma_SUITE_data/reg_m7.idl b/lib/ic/test/ic_pragma_SUITE_data/reg_m7.idl
new file mode 100644
index 0000000000..349c13b244
--- /dev/null
+++ b/lib/ic/test/ic_pragma_SUITE_data/reg_m7.idl
@@ -0,0 +1,62 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+
+// Very uggly pragmas
+
+
+#pragma prefix "P1" // Normal pragma
+
+module M4 {
+
+ module M5 {
+
+#pragma prefix "P2" // Inside a parameter list
+
+ interface I1 {
+ void Op(
+ #pragma prefix "P2" // Inside a parameter list
+ in short b,
+ #pragma prefix "P2" // Inside a parameter list
+ out short c
+ #pragma prefix "P2" // Inside a parameter list
+ );
+ };
+ typedef long T3;
+ };
+
+};
+
+
+
+/*
+
+ Specified types with the following scoped names
+ and RepositoryIds
+
+ ::M4::M5::T3 IDL:P2/T3:1.0
+
+*/
+
+
+
+
+
+
+
+
diff --git a/lib/ic/test/ic_pragma_SUITE_data/uggly.idl b/lib/ic/test/ic_pragma_SUITE_data/uggly.idl
new file mode 100644
index 0000000000..8ed3ac57ec
--- /dev/null
+++ b/lib/ic/test/ic_pragma_SUITE_data/uggly.idl
@@ -0,0 +1,204 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+// Really uggly pragmas
+
+
+struct S {
+
+#pragma ID TDL1 "LOCAL:SomeLocalId:1"
+#pragma ID TDL1 "LOCAL:SomeLocalId:2"
+
+long a
+
+#pragma ID TDL1 "LOCAL:SomeLocalId:3"
+#pragma ID TDL1 "LOCAL:SomeLocalId:4"
+
+;
+
+#pragma ID TDL1 "LOCAL:SomeLocalId:5"
+#pragma ID TDL1 "LOCAL:SomeLocalId:6"
+
+long b
+
+#pragma ID TDL1 "LOCAL:SomeLocalId:7"
+#pragma ID TDL1 "LOCAL:SomeLocalId:8"
+
+;
+
+
+#pragma ID TDL1 "LOCAL:SomeLocalId:9"
+#pragma ID TDL1 "LOCAL:SomeLocalId:10"
+
+};
+
+
+typedef long TDL1;
+
+
+exception Exc1{
+
+#pragma version Exc1 2.2
+#pragma ID TDL2 "LOCAL:SomeLocalId:11"
+
+};
+
+
+typedef long TDL2;
+
+
+exception Exc2 {
+
+#pragma version Exc2 2.2
+#pragma ID TDL3 "LOCAL:SomeLocalId:11"
+
+ long a
+
+#pragma ID TDL3 "LOCAL:SomeLocalId:12"
+#pragma ID TDL3 "LOCAL:SomeLocalId:13"
+
+ ;
+
+#pragma ID TDL3 "LOCAL:SomeLocalId:14"
+#pragma ID TDL3 "LOCAL:SomeLocalId:15"
+
+ long b
+
+#pragma ID TDL3 "LOCAL:SomeLocalId:16"
+
+ ;
+
+#pragma ID TDL3 "LOCAL:SomeLocalId:17"
+
+
+};
+
+typedef long TDL3;
+
+enum E {
+#pragma ID E "LOCAL:SomeLocalId:18"
+ a
+#pragma ID E "LOCAL:SomeLocalId:19"
+ ,
+#pragma ID E "LOCAL:SomeLocalId:20"
+ b
+#pragma ID E "LOCAL:SomeLocalId:21"
+,
+#pragma ID E "LOCAL:SomeLocalId:22"
+ c
+#pragma ID E "LOCAL:SomeLocalId:23"
+};
+
+
+
+union U switch (long) {
+
+#pragma ID TDL4 "LOCAL:SomeLocalId:24"
+
+ case 1:
+
+#pragma ID TDL4 "LOCAL:SomeLocalId:25"
+
+ long a
+
+#pragma ID TDL4 "LOCAL:SomeLocalId:26"
+
+;
+
+#pragma ID TDL4 "LOCAL:SomeLocalId:27"
+
+ case 2:
+
+#pragma ID TDL4 "LOCAL:SomeLocalId:28"
+
+ case 3:
+
+#pragma ID TDL4 "LOCAL:SomeLocalId:29"
+
+long b
+
+#pragma ID TDL4 "LOCAL:SomeLocalId:30"
+
+;
+
+#pragma ID TDL4 "LOCAL:SomeLocalId:31"
+
+ default :
+
+#pragma ID TDL4 "LOCAL:SomeLocalId:32"
+
+long c
+
+#pragma ID TDL4 "LOCAL:SomeLocalId:33"
+
+;
+
+#pragma ID TDL4 "LOCAL:SomeLocalId:34"
+
+};
+
+
+typedef long TDL4;
+
+
+
+module M {
+
+ interface I {
+
+ void fun1(
+
+#pragma version fun1 3.0
+#pragma ID TDL5 "LOCAL:SomeLocalId:35"
+
+ in short b
+
+#pragma ID TDL5 "LOCAL:SomeLocalId:36"
+#pragma ID TDL5 "LOCAL:SomeLocalId:37"
+
+ ,
+
+#pragma ID TDL5 "LOCAL:SomeLocalId:38"
+#pragma ID TDL5 "LOCAL:SomeLocalId:39"
+
+ out short c
+
+#pragma ID TDL5 "LOCAL:SomeLocalId:40"
+#pragma ID TDL5 "LOCAL:SomeLocalId:41"
+
+ );
+
+
+ typedef long TDL5;
+
+
+ void fun2(
+
+#pragma ID TDL6 "LOCAL:SomeLocalId:42"
+#pragma ID TDL6 "LOCAL:SomeLocalId:43"
+
+ );
+
+ typedef long TDL6;
+
+ };
+
+
+
+};
+
diff --git a/lib/ic/test/ic_register_SUITE.erl b/lib/ic/test/ic_register_SUITE.erl
new file mode 100644
index 0000000000..ae7578199a
--- /dev/null
+++ b/lib/ic/test/ic_register_SUITE.erl
@@ -0,0 +1,425 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+%%-----------------------------------------------------------------
+%% File: ic_register_SUITE.erl
+%%
+%% Description:
+%% Test suite for the IFR object registration
+%%
+%%-----------------------------------------------------------------
+-module(ic_register_SUITE).
+
+-include("test_server.hrl").
+-include_lib("orber/include/corba.hrl").
+%%-----------------------------------------------------------------
+%% External exports
+%%-----------------------------------------------------------------
+-export([all/1, init_all/1, finish_all/1, ifr_reg_unreg/1]).
+-export([ifr_inheritence_reg/1,ifr_reg_unreg_with_inheritence/1]).
+-export([ifr_reg_unreg_with_inheritence_bad_order/1]).
+
+%%-----------------------------------------------------------------
+%% Internal exports
+%%-----------------------------------------------------------------
+-export([]).
+
+%%-----------------------------------------------------------------
+%% Macros
+%%-----------------------------------------------------------------
+-define(REMAP_EXCEPT(F), case catch F of
+ {'EXCEPTION', E} -> exit(E);
+ R -> R
+ end).
+%% Standard options to the ic compiler, NOTE unholy use of OutDir
+
+-define(OUT(X), filename:join([?config(priv_dir, Config), gen, to_list(X)])).
+
+
+%%-----------------------------------------------------------------
+%% Func: all/1
+%% Args:
+%% Returns:
+%%-----------------------------------------------------------------
+all(doc) -> ["Description", "more description"];
+all(suite) -> {req,
+ [mnesia],
+ {conf, init_all, cases(), finish_all}}.
+
+cases() ->
+ [ifr_reg_unreg,ifr_reg_unreg_with_inheritence,
+ ifr_reg_unreg_with_inheritence_bad_order,ifr_inheritence_reg].
+
+%%-----------------------------------------------------------------
+%% Init and cleanup functions.
+%%-----------------------------------------------------------------
+
+init_all(Config) ->
+ io:format("Setting up.....~n"),
+ mnesia:stop(),
+ mnesia:delete_schema([node()]),
+ mnesia:create_schema([node()]),
+ mnesia:start(),
+ orber:install([node()]),
+ orber:start(),
+ if
+ is_list(Config) ->
+ Config;
+ true ->
+ exit("Config not a list")
+ end.
+
+finish_all(Config) ->
+ io:format("Setting down.....~n"),
+ orber:stop(),
+ orber:uninstall(),
+ mnesia:stop(),
+ mnesia:delete_schema([node()]),
+ Config.
+
+
+
+%%-----------------------------------------------------------------
+%% Test Case: IFR type registration
+%%-----------------------------------------------------------------
+ifr_reg_unreg(doc) ->
+ ["Checks that the generated register/unregister "
+ "code for the IFR is correct."];
+ifr_reg_unreg(suite) -> [];
+ifr_reg_unreg(Config) when is_list(Config) ->
+ ?REMAP_EXCEPT(ifr_reg_unregt_run(Config)).
+
+ifr_reg_unregt_run(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(ifr_reg_unreg),
+ File0 = filename:join(DataDir, reg_m8),
+ File1 = filename:join(DataDir, reg_m9),
+ File2 = filename:join(DataDir, reg_m10),
+ ?line ok = ic:gen(File0, stdopts(OutDir)++[{preproc_flags,
+ "-I" ++ DataDir}] ),
+ ?line {ok, []} = ic:gen(File0, stdopts(OutDir)++[silent2, {preproc_flags,
+ "-I" ++ DataDir}]),
+ ?line ok = ic:gen(File1, stdopts(OutDir)++[{preproc_flags,
+ "-I" ++ DataDir}] ),
+ ?line {ok, []} = ic:gen(File1, stdopts(OutDir)++[silent2, {preproc_flags,
+ "-I" ++ DataDir}]),
+ ?line ok = ic:gen(File2, stdopts(OutDir)++[{preproc_flags,
+ "-I" ++ DataDir}] ),
+ ?line {ok, []} = ic:gen(File2, stdopts(OutDir)++[silent2, {preproc_flags,
+ "-I" ++ DataDir}]),
+ ?line ok = compile(OutDir, ifr_reg_unreg_files()),
+ code:add_pathz(OutDir),
+ ?line ok = 'oe_reg_m8':'oe_register'(),
+ ?line ok = 'oe_reg_m9':'oe_register'(),
+ ?line ok = 'oe_reg_m10':'oe_register'(),
+ ?line ok = 'oe_reg_m10':'oe_unregister'(),
+ ?line ok = 'oe_reg_m9':'oe_unregister'(),
+ ?line ok = 'oe_reg_m8':'oe_unregister'(),
+ code:del_path(OutDir),
+ ok.
+
+ifr_reg_unreg_files() -> ['oe_reg_m8', 'oe_reg_m9', 'oe_reg_m10'].
+
+
+
+%%-----------------------------------------------------------------
+%% Test Case: IFR registration when object inheritence
+%% is applied and registered.
+%%-----------------------------------------------------------------
+ifr_reg_unreg_with_inheritence(doc) ->
+ ["Checks that the generated register/unregister "
+ "code for the IFR is correct, and works even when"
+ "the object inheritence is registered. This fixes"
+ "two bugs in ifr that caused crash when trying to"
+ "use OE_register/OE_unregister in a sequence of"
+ "compiled files that contained interfaces who"
+ "inherited others in sequence."];
+ifr_reg_unreg_with_inheritence(suite) -> [];
+ifr_reg_unreg_with_inheritence(Config) when is_list(Config) ->
+ ?REMAP_EXCEPT(ifr_reg_unreg_with_inheritence_run(Config)).
+
+ifr_reg_unreg_with_inheritence_run(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(ifr_reg_unreg),
+ File0 = filename:join(DataDir, reg_m8),
+ File1 = filename:join(DataDir, reg_m9),
+ File2 = filename:join(DataDir, reg_m10),
+ File3 = filename:join(DataDir, reg_m11),
+ File4 = filename:join(DataDir, reg_m12),
+ ?line ok = ic:gen(File0, stdopts(OutDir)++[{preproc_flags,
+ "-I" ++ DataDir}] ),
+ ?line {ok, []} = ic:gen(File0, stdopts(OutDir)++[silent2, {preproc_flags,
+ "-I" ++ DataDir}]),
+ ?line ok = ic:gen(File1, stdopts(OutDir)++[{preproc_flags,
+ "-I" ++ DataDir}] ),
+ ?line {ok, []} = ic:gen(File1, stdopts(OutDir)++[silent2, {preproc_flags,
+ "-I" ++ DataDir}]),
+ ?line ok = ic:gen(File2, stdopts(OutDir)++[{preproc_flags,
+ "-I" ++ DataDir}] ),
+ ?line {ok, []} = ic:gen(File2, stdopts(OutDir)++[silent2, {preproc_flags,
+ "-I" ++ DataDir}]),
+ ?line ok = ic:gen(File3, stdopts(OutDir)++[{preproc_flags,
+ "-I" ++ DataDir}] ),
+ ?line {ok, []} = ic:gen(File3, stdopts(OutDir)++[silent2, {preproc_flags,
+ "-I" ++ DataDir}]),
+ ?line ok = ic:gen(File4, stdopts(OutDir)++[{preproc_flags,
+ "-I" ++ DataDir}] ),
+ ?line {ok, []} = ic:gen(File4, stdopts(OutDir)++[silent2, {preproc_flags,
+ "-I" ++ DataDir}]),
+ ?line ok = compile(OutDir, ifr_reg_unreg_with_inheritence_files()),
+ code:add_pathz(OutDir),
+ ?line ok = 'oe_reg_m8':'oe_register'(),
+ ?line ok = 'oe_reg_m9':'oe_register'(),
+ ?line ok = 'oe_reg_m10':'oe_register'(),
+ ?line ok = 'oe_reg_m11':'oe_register'(),
+ ?line ok = 'oe_reg_m12':'oe_register'(),
+ ?line ok = 'oe_reg_m8':'oe_unregister'(),
+ ?line ok = 'oe_reg_m9':'oe_unregister'(),
+ ?line ok = 'oe_reg_m10':'oe_unregister'(),
+ ?line ok = 'oe_reg_m11':'oe_unregister'(),
+ ?line ok = 'oe_reg_m12':'oe_unregister'(),
+ code:del_path(OutDir),
+ ok.
+
+ifr_reg_unreg_with_inheritence_files() ->
+ ['oe_reg_m8', 'oe_reg_m9', 'oe_reg_m10', 'oe_reg_m11', 'oe_reg_m12'].
+
+
+
+
+
+%%-----------------------------------------------------------------
+%% Test Case: IFR registration when object inheritence
+%% is applied and registered in a bad order.
+%% Modules included and used from an ifr object
+%% are not allready registered when the current
+%% object is getting registered.
+%%-----------------------------------------------------------------
+ifr_reg_unreg_with_inheritence_bad_order(doc) ->
+ ["This tests that ifr registration is done with
+ the right write order."
+ "Modules included and used from an ifr object"
+ "are tested if allready registered when the "
+ "current object is getting registered."];
+ifr_reg_unreg_with_inheritence_bad_order(suite) -> [];
+ifr_reg_unreg_with_inheritence_bad_order(Config) when is_list(Config) ->
+ ?REMAP_EXCEPT(ifr_reg_unreg_with_inheritence_bad_order_run(Config)).
+
+ifr_reg_unreg_with_inheritence_bad_order_run(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(ifr_reg_unreg),
+ File1 = filename:join(DataDir, reg_m9),
+ File2 = filename:join(DataDir, reg_m10),
+ File4 = filename:join(DataDir, reg_m12),
+ ?line ok = ic:gen(File1, stdopts(OutDir)++[{preproc_flags,
+ "-I" ++ DataDir}] ),
+ ?line {ok, []} = ic:gen(File1, stdopts(OutDir)++[silent2, {preproc_flags,
+ "-I" ++ DataDir}]),
+ ?line ok = ic:gen(File2, stdopts(OutDir)++[{preproc_flags,
+ "-I" ++ DataDir}] ),
+ ?line {ok, []} = ic:gen(File2, stdopts(OutDir)++[silent2, {preproc_flags,
+ "-I" ++ DataDir}]),
+ ?line ok = ic:gen(File4, stdopts(OutDir)++[{preproc_flags,
+ "-I" ++ DataDir}] ),
+ ?line {ok, []} = ic:gen(File4, stdopts(OutDir)++[silent2, {preproc_flags,
+ "-I" ++ DataDir}]),
+ ?line ok = compile(OutDir, ifr_reg_unreg_with_inheritence_files()),
+ code:add_pathz(OutDir),
+ case catch 'oe_reg_m12':'oe_register'() of
+ {'EXIT',Reason1} ->
+ io:format("IFR object missing detected : ~p~n",[Reason1]),
+ true;
+ _ ->
+ test_server:fail("Failed to detect object missing : IDL:M1:1.0~n")
+ end,
+ ?line ok = 'oe_reg_m9':'oe_register'(),
+ case catch 'oe_reg_m10':'oe_register'() of
+ {'EXIT',Reason2} ->
+ io:format("IFR object missing detected : ~p~n",[Reason2]),
+ true;
+ _ ->
+ test_server:fail("Failed to detect object missing : IDL:M0:1.0~n")
+ end,
+ ?line ok = 'oe_reg_m9':'oe_unregister'(),
+ code:del_path(OutDir),
+ ok.
+
+
+
+%%-----------------------------------------------------------------
+%% Test Case: IFR registration with inheritence
+%%-----------------------------------------------------------------
+ifr_inheritence_reg(doc) ->
+ ["Checks that IFR object inheritence is correctly registered."];
+ifr_inheritence_reg(suite) -> [];
+ifr_inheritence_reg(Config) when is_list(Config) ->
+ ?REMAP_EXCEPT(ifr_inh_reg_run(Config)).
+
+ifr_inh_reg_run(Config) ->
+ DataDir = ?config(data_dir, Config),
+ OutDir = ?OUT(ifr_reg_unreg),
+ File0 = filename:join(DataDir, reg_m8),
+ File1 = filename:join(DataDir, reg_m9),
+ File2 = filename:join(DataDir, reg_m10),
+ File3 = filename:join(DataDir, reg_m11),
+ File4 = filename:join(DataDir, reg_m12),
+ ?line ok = ic:gen(File0, stdopts(OutDir)++[{preproc_flags,
+ "-I" ++ DataDir}] ),
+ ?line {ok, []} = ic:gen(File0, stdopts(OutDir)++[silent2, {preproc_flags,
+ "-I" ++ DataDir}]),
+ ?line ok = ic:gen(File1, stdopts(OutDir)++[{preproc_flags,
+ "-I" ++ DataDir}] ),
+ ?line {ok, []} = ic:gen(File1, stdopts(OutDir)++[silent2, {preproc_flags,
+ "-I" ++ DataDir}]),
+ ?line ok = ic:gen(File2, stdopts(OutDir)++[{preproc_flags,
+ "-I" ++ DataDir}] ),
+ ?line {ok, []} = ic:gen(File2, stdopts(OutDir)++[silent2, {preproc_flags,
+ "-I" ++ DataDir}]),
+ ?line ok = ic:gen(File3, stdopts(OutDir)++[{preproc_flags,
+ "-I" ++ DataDir}] ),
+ ?line {ok, []} = ic:gen(File3, stdopts(OutDir)++[silent2, {preproc_flags,
+ "-I" ++ DataDir}]),
+ ?line ok = ic:gen(File4, stdopts(OutDir)++[{preproc_flags,
+ "-I" ++ DataDir}] ),
+ ?line {ok, []} = ic:gen(File4, stdopts(OutDir)++[silent2, {preproc_flags,
+ "-I" ++ DataDir}]),
+ ?line ok = compile(OutDir, ifr_reg_unreg_with_inheritence_files()),
+ code:add_pathz(OutDir),
+ %% OE_register for all files
+ ?line ok = 'oe_reg_m8':'oe_register'(),
+ ?line ok = 'oe_reg_m9':'oe_register'(),
+ ?line ok = 'oe_reg_m10':'oe_register'(),
+ ?line ok = 'oe_reg_m11':'oe_register'(),
+ ?line ok = 'oe_reg_m12':'oe_register'(),
+
+ %% Inheritence registration test
+ OE_IFR = orber_ifr:find_repository(),
+ %% Interfaces that not inherit from other interfaces
+ ?line [] = get_inh(OE_IFR, "IDL:m0/i0:1.0"),
+ ?line [] = get_inh(OE_IFR, "IDL:m1/i1:1.0"),
+ ?line [] = get_inh(OE_IFR, "IDL:m3/i3:1.0"),
+ %% Interfaces that inherit from other interfaces
+ ?line ["IDL:m1/i1:1.0"] = get_inh(OE_IFR, "IDL:m2/i2:1.0"),
+ ?line ["IDL:m1/i1:1.0","IDL:m2/i2:1.0"] = get_inh(OE_IFR, "IDL:m4/i4:1.0"),
+ ?line ["IDL:m3/i3:1.0"] = get_inh(OE_IFR, "IDL:m4/i5:1.0"),
+
+ %% OE_unregister for all files
+ ?line ok = 'oe_reg_m8':'oe_unregister'(),
+ ?line ok = 'oe_reg_m9':'oe_unregister'(),
+ ?line ok = 'oe_reg_m10':'oe_unregister'(),
+ ?line ok = 'oe_reg_m11':'oe_unregister'(),
+ ?line ok = 'oe_reg_m12':'oe_unregister'(),
+ code:del_path(OutDir),
+ ok.
+
+
+get_inh(OE_IFR,ID) ->
+ OE_CURRENT = orber_ifr:lookup_id(OE_IFR,ID),
+ INH_LIST = orber_ifr:get_base_interfaces(OE_CURRENT),
+ case INH_LIST of
+ [] ->
+ io:format("~nInterface ~p inherits from nobody.~n",[ID]),
+ [];
+ _ ->
+ print_inh_list_ids(ID, INH_LIST, [])
+ end.
+
+print_inh_list_ids(_ID, [], Acc) ->
+ lists:reverse(Acc);
+print_inh_list_ids(ID, [H|T], Acc) ->
+ io:format("~n"),
+ Parent = orber_ifr:get_id(H),
+ io:format("Interface ~p inherits from ~p.~n", [ID, Parent]),
+ print_inh_list_ids(ID, T, [Parent|Acc]).
+
+
+
+
+stdopts(OutDir) ->
+ [{outdir, OutDir}, {maxerrs, infinity}].
+
+
+compile(Dir, Files) ->
+ compile(Dir, Files, []).
+
+compile(Dir, Files, Opts) ->
+ {ok, Cwd} = file:get_cwd(),
+ file:set_cwd(Dir),
+ io:format("Changing to ~p~n", [Dir]),
+ case catch do_compile(Files, Opts) of
+ ok ->
+ file:set_cwd(Cwd);
+ Err ->
+ file:set_cwd(Cwd),
+ test_server:fail(Err)
+ end.
+
+do_compile([], _Opts) -> ok;
+do_compile([F | Fs], Opts) ->
+ io:format("Compiling ~p", [F]),
+ case compile:file(F, Opts) of
+ ok ->
+ io:format(" ok~n", []),
+ do_load(F, Opts),
+ do_compile(Fs, Opts);
+ {ok, _} ->
+ io:format(" ok~n", []),
+ do_load(F, Opts),
+ do_compile(Fs, Opts);
+ {ok, _, _} ->
+ io:format(" ok~n", []),
+ do_load(F, Opts),
+ do_compile(Fs, Opts);
+ Err ->
+ io:format(" error: ~p~n", [Err]),
+ Err
+ end.
+
+do_load(File, Opts) ->
+ case lists:member(load, Opts) of
+ true ->
+ io:format("Loading file ~p", [File]),
+ code:purge(File),
+ R = code:load_abs(File),
+ io:format("Loaded: ~p", [R]);
+ false ->
+ ok
+ end.
+
+
+to_list(X) when is_atom(X) -> atom_to_list(X);
+to_list(X) -> X.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/ic/test/ic_register_SUITE_data/reg_m10.idl b/lib/ic/test/ic_register_SUITE_data/reg_m10.idl
new file mode 100644
index 0000000000..9c1f126b64
--- /dev/null
+++ b/lib/ic/test/ic_register_SUITE_data/reg_m10.idl
@@ -0,0 +1,37 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+//
+// IDL for testing register/unregister in the IFR when using included specs
+//
+#include "reg_m9.idl"
+
+typedef sequence<long> Sequence1;
+
+#include "reg_m8.idl"
+
+module m2 {
+
+ interface i2 : m1::i1
+ {
+ short op3( in long a, inout char b, out long c );
+ };
+
+
+};
+
diff --git a/lib/ic/test/ic_register_SUITE_data/reg_m11.idl b/lib/ic/test/ic_register_SUITE_data/reg_m11.idl
new file mode 100644
index 0000000000..607d695357
--- /dev/null
+++ b/lib/ic/test/ic_register_SUITE_data/reg_m11.idl
@@ -0,0 +1,32 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+//
+// IDL for testing register/unregister in the IFR when using included specs
+//
+
+module m3 {
+
+ interface i3
+ {
+ short op4( in long a, inout char b, out long c );
+ };
+
+
+};
+
diff --git a/lib/ic/test/ic_register_SUITE_data/reg_m12.idl b/lib/ic/test/ic_register_SUITE_data/reg_m12.idl
new file mode 100644
index 0000000000..3dd9267655
--- /dev/null
+++ b/lib/ic/test/ic_register_SUITE_data/reg_m12.idl
@@ -0,0 +1,40 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+//
+// IDL for testing register/unregister in the IFR when using included specs
+// Special case with multiple inheritence.
+//
+#include "reg_m10.idl"
+#include "reg_m11.idl"
+
+module m4 {
+
+ interface i4 : m2::i2
+ {
+ short op5( in long a, inout char b, out long c );
+ };
+
+ interface i5 : m3::i3
+ {
+ short op6( in long a, inout char b, out long c );
+ };
+
+
+};
+
diff --git a/lib/ic/test/ic_register_SUITE_data/reg_m8.idl b/lib/ic/test/ic_register_SUITE_data/reg_m8.idl
new file mode 100644
index 0000000000..dc7432c05d
--- /dev/null
+++ b/lib/ic/test/ic_register_SUITE_data/reg_m8.idl
@@ -0,0 +1,32 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+//
+// IDL for testing register/unregister in the IFR when using included specs
+//
+module m0 {
+
+ interface i0 {
+ void op1( in short c );
+ float op2( in char a);
+
+ };
+
+
+};
+
diff --git a/lib/ic/test/ic_register_SUITE_data/reg_m9.idl b/lib/ic/test/ic_register_SUITE_data/reg_m9.idl
new file mode 100644
index 0000000000..e937c41608
--- /dev/null
+++ b/lib/ic/test/ic_register_SUITE_data/reg_m9.idl
@@ -0,0 +1,32 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 1998-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+//
+// IDL for testing register/unregister in the IFR when using included specs
+//
+module m1 {
+
+ interface i1 {
+ void op1( in short c );
+ float op2( in char a);
+
+ };
+
+
+};
+
diff --git a/lib/ic/test/java_client_erl_server_SUITE.erl b/lib/ic/test/java_client_erl_server_SUITE.erl
new file mode 100644
index 0000000000..ee77ef0c4e
--- /dev/null
+++ b/lib/ic/test/java_client_erl_server_SUITE.erl
@@ -0,0 +1,330 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+%%%----------------------------------------------------------------------
+%%% Purpose : Test suite for the backends of the IDL compiler
+%%%----------------------------------------------------------------------
+
+-module(java_client_erl_server_SUITE).
+-include("test_server.hrl").
+
+
+-export([all/1,init_all/1,finish_all/1,init_per_testcase/2,fin_per_testcase/2]).
+-export([marshal_ll/1,marshal_ull/1,
+ marshal_l/1,marshal_ul/1,
+ marshal_s/1,marshal_us/1,
+ marshal_c/1,marshal_wc/1,
+ marshal_str/1,
+ marshal_any_3/1,marshal_any_2/1]).
+
+
+%% Top of cases
+
+all(doc) ->
+ "Test of IC with a Java-client and an Erlang generic server. "
+ "The communication is via Erlang distribution.";
+all(suite) -> {conf,init_all,cases(),finish_all}.
+
+cases() -> [marshal_ll,marshal_ull,
+ marshal_l,marshal_ul,
+ marshal_s,marshal_us,
+ marshal_c,marshal_wc,
+ marshal_str,
+ marshal_any_3,marshal_any_2].
+
+init_all(Config) when is_list(Config) ->
+ case case code:priv_dir(jinterface) of
+ {error,bad_name} ->
+ false;
+ P ->
+ filelib:is_dir(P)
+ end
+ of
+ true ->
+ case find_executable(["java"]) of
+ false ->
+ {skip,"Found no Java VM"};
+ Path ->
+ [{java,Path}|Config]
+ end;
+ false ->
+ {skip,"No jinterface application"}
+ end.
+
+
+find_executable([]) ->
+ false;
+find_executable([E|T]) ->
+ case os:find_executable(E) of
+ false -> find_executable(T);
+ Path -> Path
+ end.
+
+finish_all(Config) -> Config.
+
+
+
+%% Add/remove code path and watchdog before/after each test case.
+%%
+init_per_testcase(_Case, Config) ->
+ DataDir = ?config(data_dir, Config),
+ code:add_patha(DataDir),
+
+ %% Since other test suites use the module m_i et,al, we have
+ %% to make sure we are using the right modules.
+ code:purge(m_i),
+ code:purge(m_i_impl),
+ code:purge(oe_java_erl_test),
+ code:load_file(m_i),
+ code:load_file(m_i_impl),
+ code:load_file(oe_java_erl_test),
+
+ WatchDog = test_server:timetrap(test_server:seconds(20)),
+ [{watchdog, WatchDog}| Config].
+
+fin_per_testcase(_Case, Config) ->
+ DataDir = ?config(data_dir, Config),
+ code:del_path(DataDir),
+ WatchDog = ?config(watchdog, Config),
+ test_server:timetrap_cancel(WatchDog).
+
+
+
+%%--------------------------------------------------------------------
+%%
+%% Test cases
+
+marshal_ll(doc) ->
+ ["Testing marshalling of IDL long long"];
+marshal_ll(suite) -> [];
+marshal_ll(Config) when is_list(Config) ->
+ ?line DataDir = ?config(data_dir, Config),
+ ?line {ok,Server} = m_i:oe_create_link([], {local,marshal_ll}),
+ ?line ok = java(?config(java, Config), DataDir, "JavaClient",
+ ["JavaClient",node(),erlang:get_cookie(),marshal_ll]),
+ ?line ok = m_i:stop(Server),
+ ok.
+
+marshal_ull(doc) ->
+ ["Testing marshalling of IDL unsigned long long"];
+marshal_ull(suite) -> [];
+marshal_ull(Config) when is_list(Config) ->
+ ?line DataDir = ?config(data_dir, Config),
+ ?line {ok,Server} = m_i:oe_create_link([], {local,marshal_ull}),
+ ?line ok = java(?config(java, Config), DataDir, "JavaClient",
+ ["JavaClient",node(),erlang:get_cookie(),marshal_ull]),
+ ?line ok = m_i:stop(Server),
+ ok.
+
+marshal_l(doc) ->
+ ["Testing marshalling of IDL long"];
+marshal_l(suite) -> [];
+marshal_l(Config) when is_list(Config) ->
+ ?line DataDir = ?config(data_dir, Config),
+ ?line {ok,Server} = m_i:oe_create_link([], {local,marshal_l}),
+ ?line ok = java(?config(java, Config), DataDir, "JavaClient",
+ ["JavaClient",node(),erlang:get_cookie(),marshal_l]),
+ ?line ok = m_i:stop(Server),
+ ok.
+
+marshal_ul(doc) ->
+ ["Testing marshalling of IDL unsigned long"];
+marshal_ul(suite) -> [];
+marshal_ul(Config) when is_list(Config) ->
+ ?line DataDir = ?config(data_dir, Config),
+ ?line {ok,Server} = m_i:oe_create_link([], {local,marshal_ul}),
+ ?line ok = java(?config(java, Config), DataDir, "JavaClient",
+ ["JavaClient",node(),erlang:get_cookie(),marshal_ul]),
+ ?line ok = m_i:stop(Server),
+ ok.
+
+marshal_s(doc) ->
+ ["Testing marshalling of IDL short"];
+marshal_s(suite) -> [];
+marshal_s(Config) when is_list(Config) ->
+ ?line DataDir = ?config(data_dir, Config),
+ ?line {ok,Server} = m_i:oe_create_link([], {local,marshal_s}),
+ ?line ok = java(?config(java, Config), DataDir, "JavaClient",
+ ["JavaClient",node(),erlang:get_cookie(),marshal_s]),
+ ?line ok = m_i:stop(Server),
+ ok.
+
+marshal_us(doc) ->
+ ["Testing marshalling of IDL unsigned short"];
+marshal_us(suite) -> [];
+marshal_us(Config) when is_list(Config) ->
+ ?line DataDir = ?config(data_dir, Config),
+ ?line {ok,Server} = m_i:oe_create_link([], {local,marshal_us}),
+ ?line ok = java(?config(java, Config), DataDir, "JavaClient",
+ ["JavaClient",node(),erlang:get_cookie(),marshal_us]),
+ ?line ok = m_i:stop(Server),
+ ok.
+
+marshal_c(doc) ->
+ ["Testing marshalling of IDL char"];
+marshal_c(suite) -> [];
+marshal_c(Config) when is_list(Config) ->
+ ?line DataDir = ?config(data_dir, Config),
+ ?line {ok,Server} = m_i:oe_create_link([], {local,marshal_c}),
+ ?line ok = java(?config(java, Config), DataDir, "JavaClient",
+ ["JavaClient",node(),erlang:get_cookie(),marshal_c]),
+ ?line ok = m_i:stop(Server),
+ ok.
+
+marshal_wc(doc) ->
+ ["Testing marshalling of IDL char"];
+marshal_wc(suite) -> [];
+marshal_wc(Config) when is_list(Config) ->
+ ?line DataDir = ?config(data_dir, Config),
+ ?line {ok,Server} = m_i:oe_create_link([], {local,marshal_wc}),
+ ?line ok = java(?config(java, Config), DataDir, "JavaClient",
+ ["JavaClient",node(),erlang:get_cookie(),marshal_wc]),
+ ?line ok = m_i:stop(Server),
+ ok.
+
+marshal_str(doc) ->
+ ["Testing marshalling of IDL string"];
+marshal_str(suite) -> [];
+marshal_str(Config) when is_list(Config) ->
+ ?line DataDir = ?config(data_dir, Config),
+ ?line {ok,Server} = m_i:oe_create_link([], {local,marshal_str}),
+ ?line ok = java(?config(java, Config), DataDir,
+%%% "-DOtpConnection.trace=4 "
+ "JavaClient",
+ ["JavaClient",node(),erlang:get_cookie(),marshal_str]),
+ ?line ok = m_i:stop(Server),
+ ok.
+
+marshal_any_3(doc) ->
+ ["Testing marshalling of IDL any"];
+marshal_any_3(suite) -> [];
+marshal_any_3(Config) when is_list(Config) ->
+ ?line DataDir = ?config(data_dir, Config),
+ ?line {ok,Server} = m_i:oe_create_link([], {local,marshal_any_3}),
+ ?line ok = java(?config(java, Config), DataDir, "JavaClient",
+ ["JavaClient",node(),erlang:get_cookie(),marshal_any_3]),
+ ?line ok = m_i:stop(Server),
+ ok.
+
+marshal_any_2(doc) ->
+ ["Testing marshalling of IDL any"];
+marshal_any_2(suite) -> [];
+marshal_any_2(Config) when is_list(Config) ->
+ ?line DataDir = ?config(data_dir, Config),
+ ?line {ok,Server} = m_i:oe_create_link([], {local,marshal_any_2}),
+ ?line ok = java(?config(java, Config), DataDir, "JavaClient",
+ ["JavaClient",node(),erlang:get_cookie(),marshal_any_2]),
+ ?line ok = m_i:stop(Server),
+ ok.
+
+%%--------------------------------------------------------------------
+%%
+%% Utilities
+
+
+java(Java, Dir, ClassAndArgs) ->
+ cmd(Java++" -classpath "++classpath(Dir)++" "++ClassAndArgs).
+
+java(Java, Dir, Class, Args) ->
+ java(Java, Dir, Class++" "++to_string(Args)).
+
+to_string([H|T]) when is_integer(H) ->
+ integer_to_list(H)++" "++to_string(T);
+to_string([H|T]) when is_atom(H) ->
+ atom_to_list(H)++" "++to_string(T);
+to_string([H|T]) when is_list(H) ->
+ lists:flatten(H)++" "++to_string(T);
+to_string([]) -> [].
+
+% javac(Dir, File) ->
+% cmd("javac -d "++Dir++" -classpath "++classpath(Dir)++" "++
+% filename:join(Dir, File)).
+
+classpath(Dir) ->
+ PS =
+ case os:type() of
+ {win32, _} -> ";";
+ _ -> ":"
+ end,
+ Dir++PS++
+ filename:join([code:lib_dir(ic),"priv","ic.jar"])++PS++
+ filename:join([code:lib_dir(jinterface),"priv","OtpErlang.jar"])++PS++
+ case os:getenv("CLASSPATH") of
+ false -> "";
+ Classpath -> Classpath
+ end.
+
+
+cmd(Cmd) ->
+ PortOpts = [{line,80},eof,exit_status,stderr_to_stdout],
+ io:format("<cmd> ~s~n", [Cmd]),
+ case catch open_port({spawn,Cmd}, PortOpts) of
+ Port when is_port(Port) ->
+ Result = cmd_loop(Port, []),
+ io:format("<cmd=~w>~n", [Result]),
+ case Result of
+ 0 -> ok;
+ ExitCode when is_integer(ExitCode) -> {error,ExitCode};
+ Error -> Error
+ end;
+ {'EXIT',Reason} ->
+ {error,Reason}
+ end.
+
+cmd_loop(Port, Line) ->
+ receive
+ {Port,eof} ->
+ receive
+ {Port,{exit_status,ExitStatus}} ->
+ ExitStatus
+ after 1 ->
+ undefined
+ end;
+ {Port,{exit_status,ExitStatus}} ->
+ receive
+ {Port,eof} ->
+ ok after 1 -> ok end,
+ ExitStatus;
+ {Port,{data,{Tag,Data}}} ->
+ case Tag of
+ eol ->
+ io:put_chars([Line|cr_to_nl(Data)]),
+ io:nl(),
+ cmd_loop(Port, []);
+ noeol ->
+ cmd_loop(Port, [Line|cr_to_nl(Data)])
+ end;
+ {'EXIT',Port,Reason} ->
+ {error,Reason};
+ Other ->
+ io:format("WARNING: Unexpected at ~s:~p: ~p~n",
+ [?MODULE_STRING,?LINE,Other]),
+ cmd_loop(Port, Line)
+ end.
+
+%% Convert lonely CR to NL, and CRLF to NL
+%%
+cr_to_nl([$\r,$\n|T]) ->
+ [$\n|cr_to_nl(T)];
+cr_to_nl([$\r|T]) ->
+ [$\n|cr_to_nl(T)];
+cr_to_nl([C|T]) ->
+ [C|cr_to_nl(T)];
+cr_to_nl([]) ->
+ [].
diff --git a/lib/ic/test/java_client_erl_server_SUITE_data/JavaClient.java b/lib/ic/test/java_client_erl_server_SUITE_data/JavaClient.java
new file mode 100644
index 0000000000..1881279ac8
--- /dev/null
+++ b/lib/ic/test/java_client_erl_server_SUITE_data/JavaClient.java
@@ -0,0 +1,759 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2003-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+ */
+public class JavaClient {
+
+ public static void main(String[] argv)
+ {
+ System.out.println("Hello World!");
+ if (argv.length < 4) {
+ System.out.println("Too few arguments!");
+ System.exit(1);
+ }
+ // for (int j = 0; j < argv.length; j++)
+ // System.out.println(argv[j]);
+ try {
+ if (argv[3].equals("marshal_ll")) {
+ System.out.println("marshal_ll");
+ marshal_ll(argv[0], argv[1], argv[2], argv[3]);
+ }
+ else if (argv[3].equals("marshal_ull")) {
+ marshal_ull(argv[0], argv[1], argv[2], argv[3]);
+ }
+ else if (argv[3].equals("marshal_l")) {
+ marshal_l(argv[0], argv[1], argv[2], argv[3]);
+ }
+ else if (argv[3].equals("marshal_ul")) {
+ marshal_ul(argv[0], argv[1], argv[2], argv[3]);
+ }
+ else if (argv[3].equals("marshal_s")) {
+ marshal_s(argv[0], argv[1], argv[2], argv[3]);
+ }
+ else if (argv[3].equals("marshal_us")) {
+ marshal_us(argv[0], argv[1], argv[2], argv[3]);
+ }
+ else if (argv[3].equals("marshal_c")) {
+ marshal_c(argv[0], argv[1], argv[2], argv[3]);
+ }
+ else if (argv[3].equals("marshal_wc")) {
+ marshal_wc(argv[0], argv[1], argv[2], argv[3]);
+ }
+ else if (argv[3].equals("marshal_str")) {
+ marshal_str(argv[0], argv[1], argv[2], argv[3]);
+ }
+ else if (argv[3].equals("marshal_any_3")) {
+ marshal_any_3(argv[0], argv[1], argv[2], argv[3]);
+ }
+ else if (argv[3].equals("marshal_any_2")) {
+ marshal_any_2(argv[0], argv[1], argv[2], argv[3]);
+ }
+ else {
+ System.out.println("Unknown test: "+argv[3]);
+ System.exit(2);
+ }
+ } catch (java.lang.Exception e) {
+ System.out.println("Exception!: "+e);
+ System.exit(3);
+ }
+ System.exit(0);
+ }
+
+
+
+ static void marshal_ll(String selfNode, String peerNode,
+ String cookie, String serverName)
+ throws java.lang.Exception
+ {
+ m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName);
+ // Just warming up..
+ System.out.println("Just warming up.."+i);
+ verify_ll(i, 3, 2, 1);
+ verify_ll(i, 5, 4, 3);
+ verify_ll(i, -128, 0, 1);
+ // The small integer border
+ verify_ll(i, 255, 0, 1);
+ verify_ll(i, 256, 0, 1);
+ // The integer border
+ verify_ll(i, (1L<<26)-1L, 0L, 1);
+ verify_ll(i, 1L<<26, 0L, 1);
+ verify_ll(i, -(1L<<26), 0L, 1);
+ verify_ll(i, (1L<<27)-1L, 0L, 1);
+ verify_ll(i, 1L<<27, 0L, 1);
+ verify_ll(i, -(1L<<27), 0L, 1);
+ // Bignum byte borders
+ verify_ll(i, (1L<<32)-1L, 0L, 1);
+ verify_ll(i, 1L<<32, 0L, 1);
+ verify_ll(i, -(1L<<32)+1L, 0L, 1);
+ verify_ll(i, -(1L<<32), 0L, 1);
+ verify_ll(i, (1L<<40)-1L, 0L, 1);
+ verify_ll(i, 1L<<40, 0L, 1);
+ verify_ll(i, -(1L<<40)+1L, 0L, 1);
+ verify_ll(i, -(1L<<40), 0L, 1);
+ verify_ll(i, (1L<<48)-1L, 0L, 1);
+ verify_ll(i, 1L<<48, 0L, 1);
+ verify_ll(i, -(1L<<48)+1L, 0L, 1);
+ verify_ll(i, -(1L<<48), 0L, 1);
+ // Java long border
+ verify_ll(i, java.lang.Long.MAX_VALUE, 0L, 1);
+ verify_ll(i, java.lang.Long.MIN_VALUE, 0L, 1);
+ verify_ll(i, -1L, 0L, 1);
+ // Impossible decodes
+ verify_ll_bad(i, java.lang.Long.MAX_VALUE, -1L, 1);
+ verify_ll_bad(i, java.lang.Long.MIN_VALUE, 1L, 1);
+ verify_ll_bad(i, java.lang.Long.MIN_VALUE, 0L, -1);
+ verify_ll_bad(i, java.lang.Long.MAX_VALUE, -1L, 2);
+ verify_ll_bad(i, java.lang.Long.MIN_VALUE, 0L, 2);
+ }
+
+ static void marshal_ull(String selfNode, String peerNode,
+ String cookie, String serverName)
+ throws java.lang.Exception
+ {
+ m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName);
+ // Just warming up..
+ verify_ull(i, 3, 2, 1);
+ verify_ull(i, 5, 4, 3);
+ // The small integer border
+ verify_ull(i, 255, 0, 1);
+ verify_ull(i, 256, 0, 1);
+ // The integer border
+ verify_ull(i, (1L<<26)-1L, 0L, 1);
+ verify_ull(i, 1L<<26, 0L, 1);
+ verify_ull(i, (1L<<27)-1L, 0L, 1);
+ verify_ull(i, 1L<<27, 0L, 1);
+ // Bignum byte borders
+ verify_ull(i, (1L<<32)-1L, 0L, 1);
+ verify_ull(i, 1L<<32, 0L, 1);
+ verify_ull(i, (1L<<40)-1L, 0L, 1);
+ verify_ull(i, 1L<<40, 0L, 1);
+ verify_ull(i, (1L<<48)-1L, 0L, 1);
+ verify_ull(i, 1L<<48, 0L, 1);
+ // Java long border
+ verify_ull(i, java.lang.Long.MAX_VALUE, 0L, 1);
+ verify_ull(i, java.lang.Long.MIN_VALUE, 0L, 1);
+ verify_ull(i, -1L, 0L, 1);
+ verify_ull(i, java.lang.Long.MAX_VALUE,
+ java.lang.Long.MIN_VALUE, 1);
+ // Impossible decodes
+ verify_ull_bad(i, -1L, -1L, 1);
+ verify_ull_bad(i, java.lang.Long.MAX_VALUE, -1L, 2);
+ }
+
+ static void marshal_l(String selfNode, String peerNode,
+ String cookie, String serverName)
+ throws java.lang.Exception
+ {
+ m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName);
+ // Just warming up..
+ verify_l(i, 3, 2, 1);
+ verify_l(i, 5, 4, 3);
+ verify_l(i, -128, 0, 1);
+ // The small integer border
+ verify_l(i, 255, 0, 1);
+ verify_l(i, 256, 0, 1);
+ // The integer border
+ verify_l(i, (1<<26)-1, 0, 1);
+ verify_l(i, 1<<26, 0, 1);
+ verify_l(i, -(1<<26), 0, 1);
+ verify_l(i, (1<<27)-1, 0, 1);
+ verify_l(i, 1<<27, 0, 1);
+ verify_l(i, -(1<<27), 0, 1);
+ // Java int border
+ verify_l(i, java.lang.Integer.MAX_VALUE, 0, 1);
+ verify_l(i, java.lang.Integer.MIN_VALUE, 0, 1);
+ // Impossible decodes
+ verify_l_bad(i, java.lang.Integer.MAX_VALUE, -1, 1);
+ verify_l_bad(i, java.lang.Integer.MIN_VALUE, 1, 1);
+ verify_l_bad(i, java.lang.Integer.MIN_VALUE, 0, -1);
+ }
+
+ static void marshal_ul(String selfNode, String peerNode,
+ String cookie, String serverName)
+ throws java.lang.Exception
+ {
+ m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName);
+ // Just warming up..
+ verify_ul(i, 3, 2, 1);
+ verify_ul(i, 5, 4, 3);
+ // The small integer border
+ verify_ul(i, 255, 0, 1);
+ verify_ul(i, 256, 0, 1);
+ // The integer border
+ verify_ul(i, (1<<26)-1, 0, 1);
+ verify_ul(i, 1<<26, 0, 1);
+ verify_ul(i, (1<<27)-1, 0, 1);
+ verify_ul(i, 1<<27, 0, 1);
+ // Java int border
+ verify_ul(i, java.lang.Integer.MAX_VALUE, 0, 1);
+ verify_ul(i, java.lang.Integer.MIN_VALUE, 0, 1);
+ verify_ul(i, -1, 0, 1);
+ verify_ul(i, java.lang.Integer.MAX_VALUE,
+ java.lang.Integer.MIN_VALUE, 1);
+ // Impossible decodes
+ verify_ul_bad(i, -1, -1, 1);
+ }
+
+ static void marshal_s(String selfNode, String peerNode,
+ String cookie, String serverName)
+ throws java.lang.Exception
+ {
+ m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName);
+ // Just warming up..
+ verify_s(i, 3, 2, 1);
+ verify_s(i, 5, 4, 3);
+ verify_s(i, -128, 0, 1);
+ // The small integer border
+ verify_s(i, 255, 0, 1);
+ verify_s(i, 256, 0, 1);
+ // Java short border
+ verify_s(i, java.lang.Short.MAX_VALUE, 0, 1);
+ verify_s(i, java.lang.Short.MIN_VALUE, 0, 1);
+ // Impossible decodes
+ verify_s_bad(i, java.lang.Short.MAX_VALUE, -1, 1);
+ verify_s_bad(i, java.lang.Short.MIN_VALUE, 1, 1);
+ verify_s_bad(i, java.lang.Short.MIN_VALUE, 0, -1);
+ }
+
+ static void marshal_us(String selfNode, String peerNode,
+ String cookie, String serverName)
+ throws java.lang.Exception
+ {
+ m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName);
+ // Just warming up..
+ verify_us(i, 3, 2, 1);
+ verify_us(i, 5, 4, 3);
+ // The small integer border
+ verify_us(i, 255, 0, 1);
+ verify_us(i, 256, 0, 1);
+ // Java short border
+ verify_us(i, java.lang.Short.MAX_VALUE, 0, 1);
+ verify_us(i, java.lang.Short.MIN_VALUE, 0, 1);
+ verify_us(i, -1, 0, 1);
+ verify_us(i, java.lang.Short.MAX_VALUE,
+ java.lang.Short.MIN_VALUE, 1);
+ // Impossible decodes
+ verify_us_bad(i, -1, -1, 1);
+ }
+
+ static void marshal_c(String selfNode, String peerNode,
+ String cookie, String serverName)
+ throws java.lang.Exception
+ {
+ m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName);
+ // Just warming up..
+ verify_c(i, '\3', '\2', 1);
+ verify_c(i, '\5', '\4', 3);
+ // The small integer border
+ verify_c(i, '\u00FF', '\0', 1);
+ verify_c(i, '\u0100', '\0', 1);
+ // Java char border
+ verify_c(i, java.lang.Character.MAX_VALUE, '\0', 1);
+ verify_c(i, java.lang.Character.MIN_VALUE, '\0', 1);
+ verify_c(i, java.lang.Character.MAX_VALUE,
+ java.lang.Character.MIN_VALUE, 1);
+ // Impossible decodes
+ verify_c_bad(i, '\u8000', '\0', 2);
+ }
+
+ static void marshal_wc(String selfNode, String peerNode,
+ String cookie, String serverName)
+ throws java.lang.Exception
+ {
+ m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName);
+ // Just warming up..
+ verify_wc(i, '\3', '\2', 1);
+ verify_wc(i, '\5', '\4', 3);
+ // The small integer border
+ verify_wc(i, '\u00FF', '\0', 1);
+ verify_wc(i, '\u0100', '\0', 1);
+ // Java char border
+ verify_wc(i, java.lang.Character.MAX_VALUE, '\0', 1);
+ verify_wc(i, java.lang.Character.MIN_VALUE, '\0', 1);
+ verify_wc(i, java.lang.Character.MAX_VALUE,
+ java.lang.Character.MIN_VALUE, 1);
+ // Impossible decodes
+ verify_c_bad(i, '\u8000', '\0', 2);
+ }
+
+ static void marshal_str(String selfNode, String peerNode,
+ String cookie, String serverName)
+ throws java.lang.Exception
+ {
+ m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName);
+ // Just warming up..
+ verify_str(i, 100, 100);
+ verify_str(i, 100, 1);
+ // Erlang string border
+ verify_str(i, 65535, 1);
+ verify_str(i, 2, 65535);
+ // Erlang string border out
+ verify_str(i, 65536, 1);
+ verify_str(i, 65536, 65536);
+ }
+
+ static void marshal_any_3(String selfNode, String peerNode,
+ String cookie, String serverName)
+ throws java.lang.Exception
+ {
+ m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName);
+ com.ericsson.otp.ic.Any x = new com.ericsson.otp.ic.Any();
+ com.ericsson.otp.ic.Any y = new com.ericsson.otp.ic.Any();
+ com.ericsson.otp.ic.Any z = new com.ericsson.otp.ic.Any();
+
+ x.insert_longlong(java.lang.Long.MAX_VALUE);
+ y.insert_longlong(1L);
+ z.insert_longlong(java.lang.Long.MAX_VALUE-1L);
+ System.out.println("verify_any_3 longlong max");
+ verify_any_3(i, x, y, 1, z);
+
+ x.insert_longlong(java.lang.Long.MIN_VALUE);
+ y.insert_longlong(-1L);
+ z.insert_longlong(java.lang.Long.MIN_VALUE+1L);
+ System.out.println("verify_any_3 longlong min");
+ verify_any_3(i, x, y, 1, z);
+
+ x.insert_ulonglong(-1L);
+ y.insert_longlong(1L);
+ z.insert_ulonglong(-2L);
+ System.out.println("verify_any_3 ulonglong max");
+ verify_any_3(i, x, y, 1, z);
+
+ x.insert_ulonglong(0L);
+ y.insert_longlong(-1L);
+ z.insert_ulonglong(1L);
+ System.out.println("verify_any_3 ulonglong min");
+ verify_any_3(i, x, y, 1, z);
+
+ x.insert_long(java.lang.Integer.MAX_VALUE);
+ y.insert_long(1);
+ z.insert_long(java.lang.Integer.MAX_VALUE-1);
+ System.out.println("verify_any_3 long max");
+ verify_any_3(i, x, y, 1, z);
+
+ x.insert_long(java.lang.Integer.MIN_VALUE);
+ y.insert_long(-1);
+ z.insert_long(java.lang.Integer.MIN_VALUE+1);
+ System.out.println("verify_any_3 long min");
+ verify_any_3(i, x, y, 1, z);
+
+ x.insert_ulong(-1);
+ y.insert_long(1);
+ z.insert_ulong(-2);
+ System.out.println("verify_any_3 ulong max");
+ verify_any_3(i, x, y, 1, z);
+
+ x.insert_ulong(0);
+ y.insert_long(-1);
+ z.insert_ulong(1);
+ System.out.println("verify_any_3 ulong min");
+ verify_any_3(i, x, y, 1, z);
+
+ x.insert_short(java.lang.Short.MAX_VALUE);
+ y.insert_short((short)1);
+ z.insert_short((short)(java.lang.Short.MAX_VALUE-1));
+ System.out.println("verify_any_3 short max");
+ verify_any_3(i, x, y, 1, z);
+
+ x.insert_short(java.lang.Short.MIN_VALUE);
+ y.insert_short((short)-1);
+ z.insert_short((short)(java.lang.Short.MIN_VALUE+1));
+ System.out.println("verify_any_3 short min");
+ verify_any_3(i, x, y, 1, z);
+
+ x.insert_ushort((short)-1);
+ y.insert_short((short)1);
+ z.insert_ushort((short)-2);
+ System.out.println("verify_any_3 ushort max");
+ verify_any_3(i, x, y, 1, z);
+
+ x.insert_ushort((short)0);
+ y.insert_short((short)-1);
+ z.insert_ushort((short)1);
+ System.out.println("verify_any_3 ushort min");
+ verify_any_3(i, x, y, 1, z);
+
+ x.insert_char('\377');
+ y.insert_char('\1');
+ z.insert_char('\376');
+ System.out.println("verify_any_3 char max");
+ verify_any_3(i, x, y, 1, z);
+
+ x.insert_wchar('\uFFFF');
+ y.insert_wchar('\u0001');
+ z.insert_wchar('\uFFFE');
+ System.out.println("verify_any_3 char max");
+ verify_any_3(i, x, y, 1, z);
+ }
+
+ static void marshal_any_2(String selfNode, String peerNode,
+ String cookie, String serverName)
+ throws java.lang.Exception
+ {
+ m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName);
+ m.s s = new m.s();
+ com.ericsson.otp.ic.Any a = new com.ericsson.otp.ic.Any();
+ //
+ s.ull_x = -1L;
+ s.ll_x = java.lang.Long.MAX_VALUE;
+ s.ll_y = 1L;
+ s.ull_z = -2L;
+ s.ll_z = java.lang.Long.MAX_VALUE-1L;
+ //
+ s.ul_x = -1;
+ s.l_x = java.lang.Integer.MAX_VALUE;
+ s.l_y = 1;
+ s.ul_z = -2;
+ s.l_z = java.lang.Integer.MAX_VALUE-1;
+ //
+ s.us_x = (short)-1;
+ s.s_x = java.lang.Short.MAX_VALUE;
+ s.s_y = (short)1;
+ s.us_z = (short)-2;
+ s.s_z = (short)(java.lang.Short.MAX_VALUE-1);
+ //
+ s.c_x = '\377';
+ s.c_y = '\1';
+ s.c_z = '\376';
+ s.wc_x = '\uFFFF';
+ s.wc_y = '\u0001';
+ s.wc_z = '\uFFFE';
+ m.sHelper.insert(a, s);
+ verify_any_2(i, a, 1);
+
+ s.ull_x = 0L;
+ s.ll_x = java.lang.Long.MIN_VALUE;
+ s.ll_y = -1L;
+ s.ull_z = 1L;
+ s.ll_z = java.lang.Long.MIN_VALUE+1L;
+ //
+ s.ul_x = 0;
+ s.l_x = java.lang.Integer.MIN_VALUE;
+ s.l_y = -1;
+ s.ul_z = 1;
+ s.l_z = java.lang.Integer.MIN_VALUE+1;
+ //
+ s.us_x = (short)0;
+ s.s_x = java.lang.Short.MIN_VALUE;
+ s.s_y = (short)-1;
+ s.us_z = (short)1;
+ s.s_z = (short)(java.lang.Short.MIN_VALUE+1);
+ //
+ s.c_x = '\0';
+ s.c_y = '\0';
+ s.c_z = '\0';
+ s.wc_x = '\u0000';
+ s.wc_y = '\u0000';
+ s.wc_z = '\u0000';
+ m.sHelper.insert(a, s);
+ verify_any_2(i, a, 1);
+ }
+
+
+ static void verify_ll(m._iStub i, long x, long y, int b)
+ throws java.lang.Exception
+ {
+ m.s a = new m.s();
+ System.out.println("verify_ll "+a);
+ a.ll_x = x;
+ a.ll_y = y;
+ long expected = (x - y)*(short)b;
+ long result = i.marshal_ll(a, (short)b);
+ if (result == expected) {
+ System.out.println("verify_ll("+x+", "+y+", "+b+") => "
+ +result);
+ } else {
+ System.out.println("verify_ll("+x+", "+y+", "+b+") => "
+ +result+" != "+expected);
+ System.exit(4);
+ }
+ }
+
+ static void verify_ull(m._iStub i, long x, long y, int b)
+ throws java.lang.Exception
+ {
+ m.s a = new m.s();
+ a.ull_x = x;
+ a.ll_y = y;
+ long expected = (x - y)*(short)b;
+ long result = i.marshal_ull(a, (short)b);
+ if (result == expected) {
+ System.out.println("verify_ull("+x+", "+y+", "+b+") => "
+ +result);
+ } else {
+ System.out.println("verify_ull("+x+", "+y+", "+b+") => "
+ +result+" != "+expected);
+ System.exit(4);
+ }
+ }
+
+ static void verify_l(m._iStub i, int x, int y, int b)
+ throws java.lang.Exception
+ {
+ m.s a = new m.s();
+ a.l_x = x;
+ a.l_y = y;
+ int expected = (x - y)*(short)b;
+ int result = i.marshal_l(a, (short)b);
+ if (result == expected) {
+ System.out.println("verify_l("+x+", "+y+", "+b+") => "
+ +result);
+ } else {
+ System.out.println("verify_l("+x+", "+y+", "+b+") => "
+ +result+" != "+expected);
+ System.exit(4);
+ }
+ }
+
+ static void verify_ul(m._iStub i, int x, int y, int b)
+ throws java.lang.Exception
+ {
+ m.s a = new m.s();
+ a.ul_x = x;
+ a.l_y = y;
+ int expected = (x - y)*(short)b;
+ int result = i.marshal_ul(a, (short)b);
+ if (result == expected) {
+ System.out.println("verify_ul("+x+", "+y+", "+b+") => "
+ +result);
+ } else {
+ System.out.println("verify_ul("+x+", "+y+", "+b+") => "
+ +result+" != "+expected);
+ System.exit(4);
+ }
+ }
+
+ static void verify_s(m._iStub i, int x, int y, int b)
+ throws java.lang.Exception
+ {
+ m.s a = new m.s();
+ a.s_x = (short)x;
+ a.s_y = (short)y;
+ short expected = (short)((x - y)*(short)b);
+ short result = i.marshal_s(a, (short)b);
+ if (result == expected) {
+ System.out.println("verify_s("+x+", "+y+", "+b+") => "
+ +result);
+ } else {
+ System.out.println("verify_s("+x+", "+y+", "+b+") => "
+ +result+" != "+expected);
+ System.exit(4);
+ }
+ }
+
+ static void verify_us(m._iStub i, int x, int y, int b)
+ throws java.lang.Exception
+ {
+ m.s a = new m.s();
+ a.us_x = (short)x;
+ a.s_y = (short)y;
+ short expected = (short)((x - y)*(short)b);
+ short result = i.marshal_us(a, (short)b);
+ if (result == expected) {
+ System.out.println("verify_us("+x+", "+y+", "+b+") => "
+ +result);
+ } else {
+ System.out.println("verify_us("+x+", "+y+", "+b+") => "
+ +result+" != "+expected);
+ System.exit(4);
+ }
+ }
+
+ static void verify_c(m._iStub i, char x, char y, int b)
+ throws java.lang.Exception
+ {
+ m.s a = new m.s();
+ a.c_x = x;
+ a.c_y = y;
+ char expected = (char)(((int)x - (int)y)*(short)b);
+ char result = i.marshal_c(a, (short)b);
+ if (result == expected) {
+ System.out.println("verify_c("+x+", "+y+", "+b+") => "
+ +result);
+ } else {
+ System.out.println("verify_c("+x+", "+y+", "+b+") => "
+ +result+" != "+expected);
+ System.exit(4);
+ }
+ }
+
+ static void verify_wc(m._iStub i, char x, char y, int b)
+ throws java.lang.Exception
+ {
+ m.s a = new m.s();
+ a.wc_x = x;
+ a.wc_y = y;
+ char expected = (char)(((int)x - (int)y)*(short)b);
+ char result = i.marshal_wc(a, (short)b);
+ if (result == expected) {
+ System.out.println("verify_wc("+x+", "+y+", "+b+") => "
+ +result);
+ } else {
+ System.out.println("verify_wc("+x+", "+y+", "+b+") => "
+ +result+" != "+expected);
+ System.exit(4);
+ }
+ }
+
+ static void verify_str(m._iStub i, int a_len, int b_len)
+ throws java.lang.Exception
+ {
+ String a = mk_str(a_len);
+ String b = mk_str(b_len);
+ String expected = a + b;
+ String result = i.strcat(a, b);
+ if (result.equals(expected)) {
+ System.out.println("verify_str(\""+a+"\", \""+b+"\") => \""
+ +result+"\"");
+ } else {
+ System.out.println("verify_str(\""+a+"\", \""+b+"\") => \""
+ +result+"\" != \""+expected.length()+"\"");
+ System.exit(4);
+ }
+ }
+
+ static String mk_str(int len)
+ throws StringIndexOutOfBoundsException
+ {
+ StringBuffer s = new StringBuffer();
+ // 17 characters is prime relative all bases of two - on purpose
+ do s.append("qwertyuiopasdfghj"); while (s.length() < len);
+ return s.substring(0, len);
+ }
+
+ static void verify_any_3(m._iStub i,
+ com.ericsson.otp.ic.Any x,
+ com.ericsson.otp.ic.Any y,
+ int b,
+ com.ericsson.otp.ic.Any expected)
+ throws java.lang.Exception
+ {
+ com.ericsson.otp.ic.Any result = i.marshal_any_3(x, y, (short)b);
+ if (! expected.equal(result)) {
+ System.exit(4);
+ }
+ }
+
+ static void verify_any_2(m._iStub i, com.ericsson.otp.ic.Any a, int b)
+ throws java.lang.Exception
+ {
+ com.ericsson.otp.ic.Any result = i.marshal_any_2(a, (short)b);
+ if (! a.equal(result)) {
+ System.exit(4);
+ }
+ }
+
+
+
+ static void verify_ll_bad(m._iStub i, long x, long y, int b)
+ throws java.lang.Exception
+ {
+ try {
+ verify_ll(i, x, y, b);
+ System.out.println("Expected exception missing!");
+ System.exit(5);
+ } catch (com.ericsson.otp.erlang.OtpErlangDecodeException e) {
+ System.out.println("Expected exception: "+e);
+ }
+ }
+
+ static void verify_ull_bad(m._iStub i, long x, long y, int b)
+ throws java.lang.Exception
+ {
+ try {
+ verify_ull(i, x, y, b);
+ System.out.println("Expected exception missing!");
+ System.exit(5);
+ } catch (com.ericsson.otp.erlang.OtpErlangDecodeException e) {
+ System.out.println("Expected exception: "+e);
+ }
+ }
+
+ static void verify_l_bad(m._iStub i, int x, int y, int b)
+ throws java.lang.Exception
+ {
+ try {
+ verify_l(i, x, y, b);
+ System.out.println("Expected exception missing!");
+ System.exit(5);
+ } catch (com.ericsson.otp.erlang.OtpErlangDecodeException e) {
+ System.out.println("Expected exception: "+e);
+ }
+ }
+
+ static void verify_ul_bad(m._iStub i, int x, int y, int b)
+ throws java.lang.Exception
+ {
+ try {
+ verify_ul(i, x, y, b);
+ System.out.println("Expected exception missing!");
+ System.exit(5);
+ } catch (com.ericsson.otp.erlang.OtpErlangDecodeException e) {
+ System.out.println("Expected exception: "+e);
+ }
+ }
+
+ static void verify_s_bad(m._iStub i, int x, int y, int b)
+ throws java.lang.Exception
+ {
+ try {
+ verify_s(i, x, y, b);
+ System.out.println("Expected exception missing!");
+ System.exit(5);
+ } catch (com.ericsson.otp.erlang.OtpErlangDecodeException e) {
+ System.out.println("Expected exception: "+e);
+ }
+ }
+
+ static void verify_us_bad(m._iStub i, int x, int y, int b)
+ throws java.lang.Exception
+ {
+ try {
+ verify_us(i, x, y, b);
+ System.out.println("Expected exception missing!");
+ System.exit(5);
+ } catch (com.ericsson.otp.erlang.OtpErlangDecodeException e) {
+ System.out.println("Expected exception: "+e);
+ }
+ }
+
+ static void verify_c_bad(m._iStub i, char x, char y, int b)
+ throws java.lang.Exception
+ {
+ try {
+ verify_c(i, x, y, b);
+ System.out.println("Expected exception missing!");
+ System.exit(5);
+ } catch (com.ericsson.otp.erlang.OtpErlangDecodeException e) {
+ System.out.println("Expected exception: "+e);
+ }
+ }
+
+ static void verify_wc_bad(m._iStub i, char x, char y, int b)
+ throws java.lang.Exception
+ {
+ try {
+ verify_wc(i, x, y, b);
+ System.out.println("Expected exception missing!");
+ System.exit(5);
+ } catch (com.ericsson.otp.erlang.OtpErlangDecodeException e) {
+ System.out.println("Expected exception: "+e);
+ }
+ }
+
+}
diff --git a/lib/ic/test/java_client_erl_server_SUITE_data/Makefile.src b/lib/ic/test/java_client_erl_server_SUITE_data/Makefile.src
new file mode 100644
index 0000000000..de1503401c
--- /dev/null
+++ b/lib/ic/test/java_client_erl_server_SUITE_data/Makefile.src
@@ -0,0 +1,88 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2003-2009. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+#
+# Makefile.src for java_client_erl_server test
+# Note: This file *must* work for both Unix and Windows
+#
+# We use both `rm' (Unix) and `del' (Windows) for removing files, but
+# with a `-' in front so that the error in not finding `rm' (`del') on
+# Windows (Unix) is ignored.
+#
+# VxWorks? XXX
+#
+
+.SUFFIXES:
+.SUFFIXES: .erl .idl .@EMULATOR@ .java
+
+
+JAVAC = @JAVAC@
+ERLC = erlc
+
+# ic variables available from ts:
+#
+# ic_libpath: @ic_libpath@
+# ic_include_path: @ic_include_path@
+
+IC_INCLUDE_PATH = @ic_include_path@
+IC_CLASSPATH = @ic_classpath@
+
+JINTERFACE_CLASSPATH = @jinterface_classpath@
+
+CLASSPATH = .@PS@$(IC_CLASSPATH)@PS@$(JINTERFACE_CLASSPATH)@PS@
+
+GEN_JAVA_FILES = \
+ m@DS@_iImplBase.java \
+ m@DS@_iStub.java \
+
+GEN_HRL_FILES = \
+ m.hrl \
+ m_i.hrl \
+ oe_java_erl_test.hrl
+
+GEN_ERL_FILES = \
+ m_i.erl \
+ oe_java_erl_test.erl
+
+JAVA_FILES = $(GEN_JAVA_FILES) JavaClient.java
+CLASS_FILES = $(JAVA_FILES:.java=.class)
+ERL_FILES = $(GEN_ERL_FILES) m_i_impl.erl
+EBINS = $(ERL_FILES:.erl=.@EMULATOR@)
+
+
+all: $(CLASS_FILES) $(EBINS)
+
+clean:
+ -rm -f $(GEN_JAVA_FILES) $(CLASS_FILES) \
+ $(GEN_ERL_FILES) $(GEN_HRL_FILES) $(EBINS)
+ -del /F /Q $(GEN_JAVA_FILES) $(CLASS_FILES) \
+ $(GEN_ERL_FILES) $(GEN_HRL_FILES) $(EBINS)
+
+$(GEN_JAVA_FILES) : java_erl_test.idl
+ $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,java}" java_erl_test.idl
+
+$(CLASS_FILES) : $(JAVA_FILES)
+ $(JAVAC) -classpath $(CLASSPATH) $(JAVA_FILES)
+
+$(GEN_ERL_FILES) $(GEN_HRL_FILES): java_erl_test.idl
+ $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,erl_genserv}" java_erl_test.idl
+
+.erl.@EMULATOR@:
+ $(ERLC) -I $(IC_INCLUDE_PATH) $<
diff --git a/lib/ic/test/java_client_erl_server_SUITE_data/java_erl_test.idl b/lib/ic/test/java_client_erl_server_SUITE_data/java_erl_test.idl
new file mode 100644
index 0000000000..b72c972d3b
--- /dev/null
+++ b/lib/ic/test/java_client_erl_server_SUITE_data/java_erl_test.idl
@@ -0,0 +1,68 @@
+
+
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 2003-2010. All Rights Reserved.
+//
+// The contents of this file are subject to the Erlang Public License,
+// Version 1.1, (the "License"); you may not use this file except in
+// compliance with the License. You should have received a copy of the
+// Erlang Public License along with this software. If not, it can be
+// retrieved online at http://www.erlang.org/.
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and limitations
+// under the License.
+//
+// %CopyrightEnd%
+module m {
+
+ struct s {
+ long long ll_x;
+ unsigned long long ull_x;
+ long long ll_y;
+ long long ll_z;
+ unsigned long long ull_z;
+
+ long l_x;
+ unsigned long ul_x;
+ long l_y;
+ long l_z;
+ unsigned long ul_z;
+
+ short s_x;
+ unsigned short us_x;
+ short s_y;
+ short s_z;
+ unsigned short us_z;
+
+ char c_x;
+ char c_y;
+ char c_z;
+
+ wchar wc_x;
+ wchar wc_y;
+ wchar wc_z;
+ };
+
+ interface i {
+ long long marshal_ll( in s a, in short b );
+ unsigned long long marshal_ull( in s a, in short b );
+
+ long marshal_l( in s a, in short b );
+ unsigned long marshal_ul( in s a, in short b );
+
+ short marshal_s( in s a, in short b );
+ unsigned short marshal_us( in s a, in short b );
+
+ char marshal_c( in s a, in short b );
+ wchar marshal_wc( in s a, in short b );
+
+ string strcat( in string a, in string b );
+
+ any marshal_any_3( in any x, in any y, in short b );
+ any marshal_any_2( in any a, in short b );
+ };
+
+};
diff --git a/lib/ic/test/java_client_erl_server_SUITE_data/m_i_impl.erl b/lib/ic/test/java_client_erl_server_SUITE_data/m_i_impl.erl
new file mode 100644
index 0000000000..77e532288f
--- /dev/null
+++ b/lib/ic/test/java_client_erl_server_SUITE_data/m_i_impl.erl
@@ -0,0 +1,169 @@
+%%--------------------------------------------------------------------
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%--------------------------------------------------------------------
+-module(m_i_impl).
+
+-export([marshal_ll/3,marshal_ull/3,
+ marshal_l/3,marshal_ul/3,
+ marshal_s/3,marshal_us/3,
+ marshal_c/3,marshal_wc/3,
+ strcat/3,
+ marshal_any_3/4,marshal_any_2/3]).
+-export([init/1,terminate/2,code_change/3]).
+
+-include("m.hrl").
+
+-define(TK_M_S, {tk_struct,
+ "IDL:m/s:1.0",
+ "s",
+ [{"ll_x",tk_longlong},
+ {"ull_x",tk_ulonglong},
+ {"ll_y",tk_longlong},
+ {"ll_z",tk_longlong},
+ {"ull_z",tk_ulonglong},
+ {"l_x",tk_long},
+ {"ul_x",tk_ulong},
+ {"l_y",tk_long},
+ {"l_z",tk_long},
+ {"ul_z",tk_ulong},
+ {"s_x",tk_short},
+ {"us_x",tk_ushort},
+ {"s_y",tk_short},
+ {"s_z",tk_short},
+ {"us_z",tk_ushort},
+ {"c_x",tk_char},
+ {"c_y",tk_char},
+ {"c_z",tk_char},
+ {"wc_x",tk_wchar},
+ {"wc_y",tk_wchar},
+ {"wc_z",tk_wchar}|_]}).
+
+
+
+marshal_ll(State, #m_s{ll_x = X, ll_y = Y}=_A, B) when integer(B) ->
+ R = (X - Y)*B,
+ io:format("~p", [{?MODULE,?LINE,[X,Y,B,R]}]),
+ {reply, R, State}.
+
+marshal_ull(State, #m_s{ull_x = X, ll_y = Y}=_A, B) when integer(B) ->
+ R = (X - Y)*B,
+ io:format("~p", [{?MODULE,?LINE,[X,Y,B,R]}]),
+ {reply, R, State}.
+
+
+marshal_l(State, #m_s{l_x = X, l_y = Y}=_A, B) when integer(B) ->
+ R = (X - Y)*B,
+ io:format("~p", [{?MODULE,?LINE,[X,Y,B,R]}]),
+ {reply, R, State}.
+
+marshal_ul(State, #m_s{ul_x = X, l_y = Y}=_A, B) when integer(B) ->
+ R = (X - Y)*B,
+ io:format("~p", [{?MODULE,?LINE,[X,Y,B,R]}]),
+ {reply, R, State}.
+
+
+marshal_s(State, #m_s{s_x = X, s_y = Y}=_A, B) when integer(B) ->
+ R = (X - Y)*B,
+ io:format("~p", [{?MODULE,?LINE,[X,Y,B,R]}]),
+ {reply, R, State}.
+
+marshal_us(State, #m_s{us_x = X, s_y = Y}=_A, B) when integer(B) ->
+ R = (X - Y)*B,
+ io:format("~p", [{?MODULE,?LINE,[X,Y,B,R]}]),
+ {reply, R, State}.
+
+
+marshal_c(State, #m_s{c_x = X, c_y = Y}=_A, B) when integer(B) ->
+ R = (X - Y)*B,
+ io:format("~p", [{?MODULE,?LINE,[X,Y,B,R]}]),
+ {reply, R, State}.
+
+marshal_wc(State, #m_s{wc_x = X, wc_y = Y}=_A, B) when integer(B) ->
+ R = (X - Y)*B,
+ io:format("~p", [{?MODULE,?LINE,[X,Y,B,R]}]),
+ {reply, R, State}.
+
+strcat(State, A, B) when list(A), list(B) ->
+ R = A++B,
+ io:format("~p", [{?MODULE,?LINE,[length(A),length(B),A,B,R]}]),
+ {reply, R, State};
+strcat(State, A, B) ->
+ io:format("~p", [{?MODULE,?LINE,[A,B]}]),
+ {reply, [], State}.
+
+marshal_any_3(State, {any,TkX,_}=X, {any,_,_}=Y, B) when integer(B) ->
+ R = any(mul(sub(any(X), any(Y)), B), TkX),
+ io:format("~p", [{?MODULE,?LINE,[X,Y,B,R]}]),
+ {reply, R, State}.
+
+marshal_any_2(State,
+ {any,TkA,#m_s{ll_x=LL_X, ull_x=ULL_X, ll_y=LL_Y,
+ l_x=L_X, ul_x=UL_X, l_y=L_Y,
+ s_x=S_X, us_x=US_X, s_y=S_Y,
+ c_x=C_X, c_y=C_Y,
+ wc_x=WC_X, wc_y=WC_Y} = A},
+ B) when integer(B) ->
+ {check_type_code,?TK_M_S} = {check_type_code,TkA},
+ ULL_Z = (ULL_X - LL_Y) * B,
+ LL_Z = (LL_X - LL_Y) * B,
+ UL_Z = (UL_X - L_Y) * B,
+ L_Z = (L_X - L_Y) * B,
+ US_Z = (US_X - S_Y) * B,
+ S_Z = (S_X - S_Y) * B,
+ C_Z = (C_X - C_Y) * B,
+ WC_Z = (WC_X - WC_Y) * B,
+ R = A#m_s{ll_z=LL_Z, ull_z=ULL_Z,
+ l_z=L_Z, ul_z=UL_Z,
+ s_z=S_Z, us_z=US_Z,
+ c_z=C_Z, wc_z=WC_Z},
+ io:format("~p", [{?MODULE,?LINE,[A,B,R]}]),
+ {reply, {any,TkA,R}, State}.
+
+
+
+init(_Env) ->
+ {ok, []}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+
+any({any,tk_longlong,X}) -> X;
+any({any,tk_long,X}) -> X;
+any({any,tk_short,X}) -> X;
+any({any,tk_ulonglong,X}) -> X;
+any({any,tk_ulong,X}) -> X;
+any({any,tk_ushort,X}) -> X;
+any({any,tk_char,X}) -> X;
+any({any,tk_wchar,X}) -> X.
+
+any(X, Tk) when integer(X) -> {any,Tk,X}.
+
+sub(X, Y) when integer(X), integer(Y) ->
+ X - Y.
+
+mul(X, Y) when integer(X), integer(Y) ->
+ X * Y.
+
+napp(0, L) -> L;
+napp(N, L) when integer(N), N >= 1 -> napp(N-1, L)++L.
diff --git a/lib/ic/vsn.mk b/lib/ic/vsn.mk
index 4aa2a04b60..074d0b3d39 100644
--- a/lib/ic/vsn.mk
+++ b/lib/ic/vsn.mk
@@ -1,20 +1 @@
IC_VSN = 4.2.25
-
-TICKETS = OTP-8639
-
-TICKETS_4.2.24 = OTP-8307 \
- OTP-8353 \
- OTP-8354 \
- OTP-8355
-
-TICKETS_4.2.23 = OTP-8201
-
-TICKETS_4.2.22 = OTP-8088
-
-TICKETS_4.2.21 = OTP-7982
-
-TICKETS_4.2.20 = OTP-7837
-
-TICKETS_4.2.19 = OTP-7595
-
-TICKETS_4.2.18 = OTP-7313
diff --git a/lib/inets/doc/src/http_client.xml b/lib/inets/doc/src/http_client.xml
index 510c30eb35..ea8053cafa 100644
--- a/lib/inets/doc/src/http_client.xml
+++ b/lib/inets/doc/src/http_client.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2009</year>
+ <year>2004</year><year>2010</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -56,8 +56,8 @@
<pre>
[{inets, [{services, [{httpc, PropertyList}]}]}]
</pre>
- <p>For valid properties see <seealso
- marker="http">http(3)</seealso></p>
+ <p>For valid properties see
+ <seealso marker="http">httpc(3)</seealso>. </p>
</section>
<section>
@@ -71,67 +71,66 @@
but not for requests to localhost. This will apply to all subsequent
requests</p>
<code type="erl">
- 2 > http:set_options([{proxy, {{"www-proxy.mycompany.com", 8000},
+ 2 > httpc:set_options([{proxy, {{"www-proxy.mycompany.com", 8000},
["localhost"]}}]).
ok
</code>
<p>An ordinary synchronous request. </p>
<code type="erl">
3 > {ok, {{Version, 200, ReasonPhrase}, Headers, Body}} =
- http:request(get, {"http://www.erlang.org", []}, [], []).
+ httpc:request(get, {"http://www.erlang.org", []}, [], []).
</code>
<p>With all default values, as above, a get request can also be written
like this.</p>
<code type="erl">
4 > {ok, {{Version, 200, ReasonPhrase}, Headers, Body}} =
- http:request("http://www.erlang.org").
+ httpc:request("http://www.erlang.org").
</code>
<p>An ordinary asynchronous request. The result will be sent
to the calling process on the form {http, {ReqestId, Result}}</p>
<code type="erl">
5 > {ok, RequestId} =
- http:request(get, {"http://www.erlang.org", []}, [], [{sync, false}]).
+ httpc:request(get, {"http://www.erlang.org", []}, [], [{sync, false}]).
</code>
<p>In this case the calling process is the shell, so we receive the
result.</p>
<code type="erl">
- 6 > receive {http, {RequestId, Result}} -> ok after 500 -> error end.
+ 6 > receive {http, {RequestId, Result}} -> ok after 500 -> error end.
ok
</code>
<p>Send a request with a specified connection header. </p>
<code type="erl">
7 > {ok, {{NewVersion, 200, NewReasonPhrase}, NewHeaders, NewBody}} =
- http:request(get, {"http://www.erlang.org", [{"connection", "close"}]},
+ httpc:request(get, {"http://www.erlang.org", [{"connection", "close"}]},
[], []).
</code>
<p>Start a HTTP client profile. </p>
<code><![CDATA[
- 8 > {ok, Pid} = inets:start(httpc, [{profile, foo}]).
+ 8 > {ok, Pid} = inets:start(httpc, [{profile, foo}]).
{ok, <0.45.0>}
]]></code>
<p>The new profile has no proxy settings so the connection will
be refused</p>
<code type="erl">
- 9 > http:request("http://www.erlang.org", foo).
- {error,econnrefused}
+ 9 > httpc:request("http://www.erlang.org", foo).
+ {error, econnrefused}
</code>
<p>Stop a HTTP client profile. </p>
<code type="erl">
- 10 > inets:stop(httpc, foo).
+ 10 > inets:stop(httpc, foo).
ok
</code>
<p>Alternatively:</p>
<code type="erl">
- 10 > inets:stop(httpc, Pid).
+ 10 > inets:stop(httpc, Pid).
ok
</code>
-
</section>
</chapter>
diff --git a/lib/inets/doc/src/inets.xml b/lib/inets/doc/src/inets.xml
index 81dfe7e944..c367d7fa77 100644
--- a/lib/inets/doc/src/inets.xml
+++ b/lib/inets/doc/src/inets.xml
@@ -13,12 +13,12 @@
compliance with the License. You should have received a copy of the
Erlang Public License along with this software. If not, it can be
retrieved online at http://www.erlang.org/.
-
+
Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
the License for the specific language governing rights and limitations
under the License.
-
+
</legalnotice>
<title>inets</title>
@@ -40,13 +40,13 @@
<title>COMMON DATA TYPES </title>
<p>Type definitions that are used more than once in
this module: </p>
- <p><c> service() = ftpc | tfptd | httpc | httpd</c></p>
+ <p><c> service() = ftpc | tftp | httpc | httpd</c></p>
<p><c> property() = atom() </c></p>
</section>
<funcs>
<func>
<name>services() -> [{Service, Pid}]</name>
- <fsummary>Returns a list of currently running services. </fsummary>
+ <fsummary>Returns a list of currently running services. </fsummary>
<type>
<v>Service = service()</v>
<v>Pid = pid()</v>
@@ -97,7 +97,7 @@
<name>start(Type) -> ok | {error, Reason}</name>
<fsummary>Starts the Inets application. </fsummary>
<type>
- <v>Type = permanent | transient | temporary</v>
+ <v>Type = permanent | transient | temporary</v>
</type>
<desc>
<p>Starts the Inets application. Default type
@@ -115,11 +115,9 @@
</func>
<func>
<name>start(Service, ServiceConfig) -> {ok, Pid} | {error, Reason}</name>
- <name>start(Service, ServiceConfig, How) -> {ok, Pid} |
- {error, Reason}</name>
+ <name>start(Service, ServiceConfig, How) -> {ok, Pid} | {error, Reason}</name>
<fsummary>Dynamically starts an inets
- service after the inets application has been
- started. </fsummary>
+ service after the inets application has been started. </fsummary>
<type>
<v>Service = service()</v>
<v>ServiceConfig = [{Option, Value}]</v>
@@ -153,9 +151,9 @@
<fsummary>Stops a started service of the inets application or takes
down a "stand_alone-service" gracefully.</fsummary>
<type>
- <v>Service = service() | stand_alone</v>
+ <v>Service = service() | stand_alone</v>
<v>Reference = pid() | term() - service specified reference</v>
- <v>Reason = term()</v>
+ <v>Reason = term()</v>
</type>
<desc>
<p>Stops a started service of the inets application or takes
@@ -169,7 +167,7 @@
<section>
<title>SEE ALSO</title>
<p><seealso marker="ftp">ftp(3)</seealso>,
- <seealso marker="http">http(3)</seealso>,
+ <seealso marker="httpc">httpc(3)</seealso>,
<seealso marker="httpd">httpd(3)</seealso>,
<seealso marker="tftp">tftp(3)</seealso></p>
</section>
diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml
index 23ad5c0df0..7b16189860 100644
--- a/lib/inets/doc/src/notes.xml
+++ b/lib/inets/doc/src/notes.xml
@@ -32,7 +32,54 @@
<file>notes.xml</file>
</header>
- <section><title>Inets 5.4</title>
+ <section><title>Inets 5.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ [httpc] If a request times out (not connect timeout), the
+ handler process exited (normal) but neglected to inform
+ the manager process. For this reason, the manager did not
+ clean up the request table., resulting in a memory leak.
+ Also the manager did not create a monitor for the
+ handler, so in an unforseen handler crash, this could
+ also create a memory leak.</p>
+ <p>
+ Own Id: OTP-8739</p>
+ </item>
+ <item>
+ <p>
+ The service tftp was spelled wrong in documentation and
+ in some parts of the code. It should be tftp.</p>
+ <p>
+ Own Id: OTP-8741 Aux Id: seq11635 </p>
+ </item>
+ <item>
+ <p>
+ [httpc] Replaced the old http client api module (http)
+ with the new, httpc in the users guide.</p>
+ <p>
+ Own Id: OTP-8742</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Eliminated warnings for auto-imported BIF clashes.</p>
+ <p>
+ Own Id: OTP-8840</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 5.4</title>
<section><title>Improvements and New Features</title>
<!--
diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl
index c34b641b7b..8af6613fa2 100644
--- a/lib/inets/src/http_client/httpc_handler.erl
+++ b/lib/inets/src/http_client/httpc_handler.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
+%%
%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
-%%
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
%%
@@ -605,24 +605,29 @@ handle_info({ssl_error, _, _} = Reason, State) ->
%% Internally, to a request handling process, a request timeout is
%% seen as a canceled request.
handle_info({timeout, RequestId},
- #state{request = #request{id = RequestId} = Request,
- canceled = Canceled} = State) ->
+ #state{request = #request{id = RequestId} = Request,
+ canceled = Canceled,
+ profile_name = ProfileName} = State) ->
?hcri("timeout of current request", [{id, RequestId}]),
httpc_response:send(Request#request.from,
httpc_response:error(Request, timeout)),
+ httpc_manager:request_done(RequestId, ProfileName),
?hcrv("response (timeout) sent - now terminate", []),
{stop, normal,
State#state{request = Request#request{from = answer_sent},
canceled = [RequestId | Canceled]}};
-handle_info({timeout, RequestId}, #state{canceled = Canceled} = State) ->
+handle_info({timeout, RequestId},
+ #state{canceled = Canceled,
+ profile_name = ProfileName} = State) ->
?hcri("timeout", [{id, RequestId}]),
Filter =
fun(#request{id = Id, from = From} = Request) when Id =:= RequestId ->
?hcrv("found request", [{id, Id}, {from, From}]),
%% Notify the owner
- Response = httpc_response:error(Request, timeout),
- httpc_response:send(From, Response),
+ httpc_response:send(From,
+ httpc_response:error(Request, timeout)),
+ httpc_manager:request_done(RequestId, ProfileName),
?hcrv("response (timeout) sent", []),
[Request#request{from = answer_sent}];
(_) ->
diff --git a/lib/inets/src/http_client/httpc_manager.erl b/lib/inets/src/http_client/httpc_manager.erl
index d5d6376369..1e1bde220b 100644
--- a/lib/inets/src/http_client/httpc_manager.erl
+++ b/lib/inets/src/http_client/httpc_manager.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
+%%
%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
-%%
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
%%
@@ -66,15 +66,6 @@
state % State of the handler: initiating | started | operational | canceled
}).
-%% Entries in the handler / request cross-ref table
-%% -record(request_info,
-%% {
-%% id, % Id of the request
-%% handler, % Pid of the handler process
-%% from, % The From value for the caller
-%% mref % Monitor ref for the caller
-%% }).
-
%%====================================================================
%% Internal Application API
@@ -577,7 +568,9 @@ handle_info({'EXIT', Pid, Reason}, #state{handler_db = HandlerDb} = State) ->
handle_info({'DOWN', _, _, Pid, _}, State) ->
%%
- %% Check what happens to waiting requests! Chall we not send a reply?
+ %% Normally this should have been cleaned up already
+ %% (when receiving {request_done, PequestId}), but
+ %% just in case there is a glitch, cleanup anyway.
%%
Pattern = #handler_info{handler = Pid, _ = '_'},
@@ -649,7 +642,16 @@ get_handler_info(Tab) ->
Acc
end,
Handlers2 = lists:foldl(F, [], Handlers1),
- Handlers3 = [{Pid, State, httpc_handler:info(Pid)} ||
+ Handlers3 = [{Pid, State,
+ case (catch httpc_handler:info(Pid)) of
+ {'EXIT', _} ->
+ %% Why would this crash?
+ %% Only if the process has died, but we don't
+ %% know about it?
+ [];
+ Else ->
+ Else
+ end} ||
{Pid, State} <- Handlers2],
Handlers3.
@@ -666,6 +668,10 @@ handle_started(StarterPid, ReqId, HandlerPid,
case ets:lookup(HandlerDb, ReqId) of
[#handler_info{state = initiating} = HandlerInfo] ->
?hcri("received started ack for initiating handler", []),
+ %% As a last resort, make sure we know when it exits,
+ %% in case it forgets to notify us.
+ %% We dont need to know the ref id?
+ erlang:monitor(process, HandlerPid),
HandlerInfo2 = HandlerInfo#handler_info{handler = HandlerPid,
state = started},
ets:insert(HandlerDb, HandlerInfo2),
diff --git a/lib/inets/src/http_client/httpc_response.erl b/lib/inets/src/http_client/httpc_response.erl
index bb9c516259..207b96271c 100644
--- a/lib/inets/src/http_client/httpc_response.erl
+++ b/lib/inets/src/http_client/httpc_response.erl
@@ -23,6 +23,8 @@
-include("httpc_internal.hrl").
%% API
+%% Avoid warning for local function error/2 clashing with autoimported BIF.
+-compile({no_auto_import,[error/2]}).
-export([parse/1, result/2, send/2, error/2, is_server_closing/1,
stream_start/3]).
diff --git a/lib/inets/src/inets_app/inets.appup.src b/lib/inets/src/inets_app/inets.appup.src
index 64fe664006..84d8c9278d 100644
--- a/lib/inets/src/inets_app/inets.appup.src
+++ b/lib/inets/src/inets_app/inets.appup.src
@@ -18,74 +18,14 @@
{"%VSN%",
[
- {"5.3.3",
+ {"5.4",
[
{restart_application, inets}
]
- },
- {"5.3.2",
- [
- {restart_application, inets}
- ]
- },
- {"5.3.1",
- [
- {restart_application, inets}
- ]
- },
- {"5.3",
- [
- {restart_application, inets}
- ]
- },
- {"5.2",
- [
- {restart_application, inets}
- ]
- },
- {"5.1.3",
- [
- {restart_application, inets}
- ]
- },
- {"5.1.2",
- [
- {restart_application, inets}
- ]
- }
+ }
],
[
- {"5.3.3",
- [
- {restart_application, inets}
- ]
- },
- {"5.3.2",
- [
- {restart_application, inets}
- ]
- },
- {"5.3.1",
- [
- {restart_application, inets}
- ]
- },
- {"5.3",
- [
- {restart_application, inets}
- ]
- },
- {"5.2",
- [
- {restart_application, inets}
- ]
- },
- {"5.1.3",
- [
- {restart_application, inets}
- ]
- },
- {"5.1.2",
+ {"5.4",
[
{restart_application, inets}
]
diff --git a/lib/inets/src/inets_app/inets.erl b/lib/inets/src/inets_app/inets.erl
index f1fa5fd997..054468e445 100644
--- a/lib/inets/src/inets_app/inets.erl
+++ b/lib/inets/src/inets_app/inets.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
+%%
%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
-%%
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
%%
@@ -57,7 +57,7 @@ start(Type) ->
%% Function: start(Service, ServiceConfig [, How]) -> {ok, Pid} |
%% {error, Reason}
%%
-%% Service = - ftpc | tftpd | httpc | httpd
+%% Service = - ftpc | tftpd | tftpc | tftp | httpc | httpd
%% ServiceConfig = ConfPropList | ConfFile
%% ConfPropList = [{Property, Value}] according to service
%% ConfFile = Path - when service is httpd
@@ -100,7 +100,7 @@ stop() ->
%%--------------------------------------------------------------------
%% Function: stop(Service, Pid) -> ok
%%
-%% Service - ftp | tftpd | http | httpd | stand_alone
+%% Service - ftpc | ftp | tftpd | tftpc | tftp | httpc | httpd | stand_alone
%%
%% Description: Stops a started service of the inets application or takes
%% down a stand alone "service" gracefully.
@@ -382,7 +382,7 @@ key1search(Key, Vals, Def) ->
%% Description: Returns a list of supported services
%%-------------------------------------------------------------------
service_names() ->
- [ftpc, tftpd, httpc, httpd].
+ [ftpc, tftp, httpc, httpd].
%%-----------------------------------------------------------------
@@ -725,8 +725,8 @@ call_service(Service, Call, Args) ->
service_module(tftpd) ->
tftp;
-service_module(httpc) ->
- httpc;
+service_module(tftpc) ->
+ tftp;
service_module(ftpc) ->
ftp;
service_module(Service) ->
diff --git a/lib/inets/test/ftp_macosx_x86_test.erl b/lib/inets/test/ftp_macosx_x86_test.erl
index c59a992421..5566d4feaa 100644
--- a/lib/inets/test/ftp_macosx_x86_test.erl
+++ b/lib/inets/test/ftp_macosx_x86_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -108,7 +108,7 @@ passive_pwd(X) -> ?LIB_MOD:passive_pwd(X).
passive_cd(X) -> ?LIB_MOD:passive_cd(X).
passive_lcd(X) -> ?LIB_MOD:passive_lcd(X).
passive_ls(X) -> ?LIB_MOD:passive_ls(X).
-passive_nlist(X) -> ?LIB_MOD:passive_nlist(X).
+passive_nlist(X) -> ?LIB_MOD:passive_nlist([{wildcard_support, false} | X]).
passive_rename(X) -> ?LIB_MOD:passive_rename(X).
passive_delete(X) -> ?LIB_MOD:passive_delete(X).
passive_mkdir(X) -> ?LIB_MOD:passive_mkdir(X).
@@ -129,7 +129,7 @@ active_pwd(X) -> ?LIB_MOD:active_pwd(X).
active_cd(X) -> ?LIB_MOD:active_cd(X).
active_lcd(X) -> ?LIB_MOD:active_lcd(X).
active_ls(X) -> ?LIB_MOD:active_ls(X).
-active_nlist(X) -> ?LIB_MOD:active_nlist(X).
+active_nlist(X) -> ?LIB_MOD:active_nlist([{wildcard_support, false} | X]).
active_rename(X) -> ?LIB_MOD:active_rename(X).
active_delete(X) -> ?LIB_MOD:active_delete(X).
active_mkdir(X) -> ?LIB_MOD:active_mkdir(X).
diff --git a/lib/inets/test/ftp_suite_lib.erl b/lib/inets/test/ftp_suite_lib.erl
index 5e27bc3a86..c539b7c17c 100644
--- a/lib/inets/test/ftp_suite_lib.erl
+++ b/lib/inets/test/ftp_suite_lib.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
+%%
%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
-%%
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
%%
@@ -508,7 +508,8 @@ passive_nlist(suite) ->
[];
passive_nlist(Config) when is_list(Config) ->
Pid = ?config(ftp, Config),
- do_nlist(Pid).
+ WildcardSupport = ?config(wildcard_support, Config),
+ do_nlist(Pid, WildcardSupport).
%%-------------------------------------------------------------------------
@@ -768,7 +769,8 @@ active_nlist(suite) ->
[];
active_nlist(Config) when is_list(Config) ->
Pid = ?config(ftp, Config),
- do_nlist(Pid).
+ WildcardSupport = ?config(wildcard_support, Config),
+ do_nlist(Pid, WildcardSupport).
%%-------------------------------------------------------------------------
@@ -1242,16 +1244,20 @@ do_ls(Pid) ->
{ok, _} = ftp:ls(Pid, "incom*"),
ok.
-do_nlist(Pid) ->
+do_nlist(Pid, WildcardSupport) ->
{ok, _} = ftp:nlist(Pid),
{ok, _} = ftp:nlist(Pid, "incoming"),
%% neither nlist nor ls operates on a directory
%% they operate on a pathname, which *can* be a
%% directory, but can also be a filename or a group
%% of files (including wildcards).
- {ok, _} = ftp:nlist(Pid, "incom*"),
-%% {error, epath} = ftp:nlist(Pid, ?BAD_DIR),
- ok.
+ case WildcardSupport of
+ true ->
+ {ok, _} = ftp:nlist(Pid, "incom*"),
+ ok;
+ _ ->
+ ok
+ end.
do_rename(Pid, Config) ->
PrivDir = ?config(priv_dir, Config),
diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl
index b5fd896001..902e440c80 100644
--- a/lib/inets/test/httpc_SUITE.erl
+++ b/lib/inets/test/httpc_SUITE.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
+%%
%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
-%%
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
%%
@@ -306,7 +306,8 @@ tickets(suite) ->
otp_8106,
otp_8056,
otp_8352,
- otp_8371
+ otp_8371,
+ otp_8739
].
@@ -2561,7 +2562,78 @@ otp_8371(Config) when is_list(Config) ->
ok.
+%%-------------------------------------------------------------------------
+otp_8739(doc) ->
+ ["OTP-8739"];
+otp_8739(suite) ->
+ [];
+otp_8739(Config) when is_list(Config) ->
+ {_DummyServerPid, Port} = otp_8739_dummy_server(),
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
+ Method = get,
+ Request = {URL, []},
+ HttpOptions = [{connect_timeout, 500}, {timeout, 1}],
+ Options = [{sync, true}],
+ case http:request(Method, Request, HttpOptions, Options) of
+ {error, timeout} ->
+ %% And now we check the size of the handler db
+ Info = httpc:info(),
+ tsp("Info: ~p", [Info]),
+ {value, {handlers, Handlers}} =
+ lists:keysearch(handlers, 1, Info),
+ case Handlers of
+ [] ->
+ ok;
+ _ ->
+ tsf({unexpected_handlers, Handlers})
+ end;
+ Unexpected ->
+ tsf({unexpected, Unexpected})
+ end.
+
+
+otp_8739_dummy_server() ->
+ Parent = self(),
+ Pid = spawn_link(fun() -> otp_8739_dummy_server_init(Parent) end),
+ receive
+ {port, Port} ->
+ {Pid, Port}
+ end.
+
+otp_8739_dummy_server_init(Parent) ->
+ {ok, ListenSocket} =
+ gen_tcp:listen(0, [binary, inet, {packet, 0},
+ {reuseaddr,true},
+ {active, false}]),
+ {ok, Port} = inet:port(ListenSocket),
+ Parent ! {port, Port},
+ otp_8739_dummy_server_main(Parent, ListenSocket).
+
+otp_8739_dummy_server_main(Parent, ListenSocket) ->
+ case gen_tcp:accept(ListenSocket) of
+ {ok, Sock} ->
+ %% Ignore the request, and simply wait for the socket to close
+ receive
+ {tcp_closed, Sock} ->
+ (catch gen_tcp:close(ListenSocket)),
+ exit(normal);
+ {tcp_error, Sock, Reason} ->
+ tsp("socket error: ~p", [Reason]),
+ (catch gen_tcp:close(ListenSocket)),
+ exit(normal)
+ after 10000 ->
+ %% Just in case
+ (catch gen_tcp:close(Sock)),
+ (catch gen_tcp:close(ListenSocket)),
+ exit(timeout)
+ end;
+ Error ->
+ exit(Error)
+ end.
+
+
+
%%--------------------------------------------------------------------
%% Internal functions
%%--------------------------------------------------------------------
diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk
index 57c87e7036..5eff9e4e3f 100644
--- a/lib/inets/vsn.mk
+++ b/lib/inets/vsn.mk
@@ -1,118 +1,5 @@
-#-*-makefile-*- ; force emacs to enter makefile-mode
-
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2010. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-
APPLICATION = inets
-INETS_VSN = 5.4
+INETS_VSN = 5.5
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)"
-TICKETS = OTP-7907 OTP-8564 OTP-8573
-
-TICKETS_5_3_3 = \
- OTP-8609 \
- OTP-8610 \
- OTP-8624
-
-TICKETS_5_3_2 = \
- OTP-8542 \
- OTP-8607
-
-TICKETS_5_3_1 = \
- OTP-8508 \
- OTP-8509
-
-TICKETS_5_3 = \
- OTP-8016 \
- OTP-8056 \
- OTP-8103 \
- OTP-8106 \
- OTP-8312 \
- OTP-8315 \
- OTP-8327 \
- OTP-8349 \
- OTP-8351 \
- OTP-8352 \
- OTP-8359 \
- OTP-8371
-
-TICKETS_5_2 = \
- OTP-8204 \
- OTP-8206 \
- OTP-8247 \
- OTP-8248 \
- OTP-8249 \
- OTP-8258 \
- OTP-8280
-
-TICKETS_5_1_3 = OTP-8154
-
-TICKETS_5_1_2 = OTP-7298 OTP-8101 OTP-8118
-
-TICKETS_5_1_1 = OTP-8052 OTP-8069
-
-TICKETS_5_1 = OTP-7994 OTP-7998 OTP-8001 OTP-8004 OTP-8005
-
-TICKETS_5_0_14 = OTP-7882 OTP-7883 OTP-7888 OTP-7950 OTP-7976
-
-TICKETS_5.0.13 = \
- OTP-7723 \
- OTP-7724 \
- OTP-7726 \
- OTP-7463 \
- OTP-7815 \
- OTP-7857
-
-# TICKETS_5.0.12 = \
-# OTP-7636
-#
-# TICKETS_5.0.11 = \
-# OTP-7574 \
-# OTP-7597 \
-# OTP-7598 \
-# OTP-7605
-#
-# TICKETS_5.0.10 = \
-# OTP-7450 \
-# OTP-7454 \
-# OTP-7490 \
-# OTP-7512
-#
-# TICKETS_5.0.9 = \
-# OTP-7257 \
-# OTP-7323 \
-# OTP-7341
-#
-# TICKETS_5.0.8 = \
-# OTP-7315 \
-# OTP-7321
-#
-# TICKETS_5.0.7 = \
-# OTP-7304
-#
-# TICKETS_5.0.6 = \
-# OTP-7266
-#
-# TICKETS_5.0.5 = \
-# OTP-7220 \
-# OTP-7221
-#
-# TICKETS_5.0.4 = \
-# OTP-7173
-#
-
diff --git a/lib/inviso/doc/src/notes.xml b/lib/inviso/doc/src/notes.xml
index 443aaf523b..48a71e314c 100644
--- a/lib/inviso/doc/src/notes.xml
+++ b/lib/inviso/doc/src/notes.xml
@@ -31,7 +31,23 @@
<p>This document describes the changes made to the Inviso application.</p>
- <section><title>Inviso 0.6.1</title>
+ <section><title>Inviso 0.6.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The obsolete guards has now been changed to the new guard
+ interface.</p>
+ <p>
+ Own Id: OTP-8747</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inviso 0.6.1</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/inviso/vsn.mk b/lib/inviso/vsn.mk
index cab3bc0ff3..79093597fe 100644
--- a/lib/inviso/vsn.mk
+++ b/lib/inviso/vsn.mk
@@ -1 +1 @@
-INVISO_VSN = 0.6.1
+INVISO_VSN = 0.6.2
diff --git a/lib/jinterface/doc/src/notes.xml b/lib/jinterface/doc/src/notes.xml
index 977a7a7f98..a571de6916 100644
--- a/lib/jinterface/doc/src/notes.xml
+++ b/lib/jinterface/doc/src/notes.xml
@@ -30,6 +30,22 @@
</header>
<p>This document describes the changes made to the Jinterface application.</p>
+<section><title>Jinterface 1.5.3.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ An pom.xml file is now generated. (Thanks to Gabor
+ Liptak.)</p>
+ <p>
+ Own Id: OTP-8841</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Jinterface 1.5.3</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpEpmd.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpEpmd.java
index 3bb678c2cc..deac528133 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpEpmd.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpEpmd.java
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2000-2009. All Rights Reserved.
+ * Copyright Ericsson AB 2000-2010. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -71,11 +71,6 @@ public class OtpEpmd {
// common values
private static final byte stopReq = (byte) 115;
- // version specific value
- private static final byte port3req = (byte) 112;
- private static final byte publish3req = (byte) 97;
- private static final byte publish3ok = (byte) 89;
-
private static final byte port4req = (byte) 122;
private static final byte port4resp = (byte) 119;
private static final byte publish4req = (byte) 120;
@@ -123,11 +118,7 @@ public class OtpEpmd {
* if there was no response from the name server.
*/
public static int lookupPort(final AbstractNode node) throws IOException {
- try {
return r4_lookupPort(node);
- } catch (final IOException e) {
- return r3_lookupPort(node);
- }
}
/**
@@ -147,11 +138,7 @@ public class OtpEpmd {
throws IOException {
Socket s = null;
- try {
- s = r4_publish(node);
- } catch (final IOException e) {
- s = r3_publish(node);
- }
+ s = r4_publish(node);
node.setEpmd(s);
@@ -196,67 +183,6 @@ public class OtpEpmd {
}
}
- private static int r3_lookupPort(final AbstractNode node)
- throws IOException {
- int port = 0;
- Socket s = null;
-
- try {
- final OtpOutputStream obuf = new OtpOutputStream();
- s = new Socket(node.host(), EpmdPort.get());
-
- // build and send epmd request
- // length[2], tag[1], alivename[n] (length = n+1)
- obuf.write2BE(node.alive().length() + 1);
- obuf.write1(port3req);
- obuf.writeN(node.alive().getBytes());
-
- // send request
- obuf.writeTo(s.getOutputStream());
-
- if (traceLevel >= traceThreshold) {
- System.out.println("-> LOOKUP (r3) " + node);
- }
-
- // receive and decode reply
- final byte[] tmpbuf = new byte[100];
-
- s.getInputStream().read(tmpbuf);
- final OtpInputStream ibuf = new OtpInputStream(tmpbuf, 0);
-
- port = ibuf.read2BE();
- } catch (final IOException e) {
- if (traceLevel >= traceThreshold) {
- System.out.println("<- (no response)");
- }
- throw new IOException("Nameserver not responding on " + node.host()
- + " when looking up " + node.alive());
- } catch (final OtpErlangDecodeException e) {
- if (traceLevel >= traceThreshold) {
- System.out.println("<- (invalid response)");
- }
- throw new IOException("Nameserver not responding on " + node.host()
- + " when looking up " + node.alive());
- } finally {
- try {
- if (s != null) {
- s.close();
- }
- } catch (final IOException e) { /* ignore close errors */
- }
- s = null;
- }
-
- if (traceLevel >= traceThreshold) {
- if (port == 0) {
- System.out.println("<- NOT FOUND");
- } else {
- System.out.println("<- PORT " + port);
- }
- }
- return port;
- }
-
private static int r4_lookupPort(final AbstractNode node)
throws IOException {
int port = 0;
@@ -288,8 +214,6 @@ public class OtpEpmd {
final int n = s.getInputStream().read(tmpbuf);
if (n < 0) {
- // this was an r3 node => not a failure (yet)
-
s.close();
throw new IOException("Nameserver not responding on "
+ node.host() + " when looking up " + node.alive());
@@ -342,81 +266,13 @@ public class OtpEpmd {
return port;
}
- private static Socket r3_publish(final OtpLocalNode node)
- throws IOException {
- Socket s = null;
-
- try {
- final OtpOutputStream obuf = new OtpOutputStream();
- s = new Socket((String) null, EpmdPort.get());
-
- obuf.write2BE(node.alive().length() + 3);
-
- obuf.write1(publish3req);
- obuf.write2BE(node.port());
- obuf.writeN(node.alive().getBytes());
-
- // send request
- obuf.writeTo(s.getOutputStream());
- if (traceLevel >= traceThreshold) {
- System.out.println("-> PUBLISH (r3) " + node + " port="
- + node.port());
- }
-
- final byte[] tmpbuf = new byte[100];
-
- final int n = s.getInputStream().read(tmpbuf);
-
- if (n < 0) {
- s.close();
- if (traceLevel >= traceThreshold) {
- System.out.println("<- (no response)");
- }
- return null;
- }
-
- final OtpInputStream ibuf = new OtpInputStream(tmpbuf, 0);
-
- if (ibuf.read1() == publish3ok) {
- node.creation = ibuf.read2BE();
- if (traceLevel >= traceThreshold) {
- System.out.println("<- OK");
- }
- return s; // success - don't close socket
- }
- } catch (final IOException e) {
- // epmd closed the connection = fail
- if (s != null) {
- s.close();
- }
- if (traceLevel >= traceThreshold) {
- System.out.println("<- (no response)");
- }
- throw new IOException("Nameserver not responding on " + node.host()
- + " when publishing " + node.alive());
- } catch (final OtpErlangDecodeException e) {
- if (s != null) {
- s.close();
- }
- if (traceLevel >= traceThreshold) {
- System.out.println("<- (invalid response)");
- }
- throw new IOException("Nameserver not responding on " + node.host()
- + " when publishing " + node.alive());
- }
-
- if (s != null) {
- s.close();
- }
- return null; // failure
- }
-
/*
- * this function will get an exception if it tries to talk to an r3 epmd, or
- * if something else happens that it cannot forsee. In both cases we return
- * an exception (and the caller should try again, using the r3 protocol). If
- * we manage to successfully communicate with an r4 epmd, we return either
- * the socket, or null, depending on the result.
+ * this function will get an exception if it tries to talk to a
+ * very old epmd, or if something else happens that it cannot
+ * forsee. In both cases we return an exception. We no longer
+ * support r3, so the exception is fatal. If we manage to
+ * successfully communicate with an r4 epmd, we return either the
+ * socket, or null, depending on the result.
*/
private static Socket r4_publish(final OtpLocalNode node)
throws IOException {
@@ -454,7 +310,6 @@ public class OtpEpmd {
final int n = s.getInputStream().read(tmpbuf);
if (n < 0) {
- // this was an r3 node => not a failure (yet)
if (s != null) {
s.close();
}
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java
index 4146bd3ced..a9712aa2ba 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java
@@ -678,6 +678,11 @@ public class OtpMbox {
return m.self.equals(self);
}
+ @Override
+ public int hashCode() {
+ return self.hashCode();
+ }
+
/*
* called by OtpNode to deliver message to this mailbox.
*
diff --git a/lib/jinterface/test/Makefile b/lib/jinterface/test/Makefile
new file mode 100644
index 0000000000..36955d1e91
--- /dev/null
+++ b/lib/jinterface/test/Makefile
@@ -0,0 +1,84 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2004-2010. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../vsn.mk
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/jinterface_test
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+TEST_SPEC_FILE = jinterface.dynspec
+
+MODULES = nc_SUITE \
+ jinterface_SUITE
+
+GEN_MODULES = jitu
+
+ERL_FILES = $(MODULES:%=%.erl) $(GEN_MODULES:%=%.erl)
+
+GEN_TARGET_FILES = $(GEN_MODULES:%=%.$(EMULATOR))
+
+SUITE_TARGET_FILES = $(MODULES:%=%.$(EMULATOR))
+
+TARGET_FILES = \
+ $(GEN_TARGET_FILES) \
+ $(SUITE_TARGET_FILES)
+
+# ----------------------------------------------------
+# PROGRAMS
+# ----------------------------------------------------
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+tests debug opt:
+
+clean:
+ rm -f $(TARGET_FILES)
+ rm -f errs core *~
+
+docs:
+
+# ----------------------------------------------------
+# Special Targets
+# ----------------------------------------------------
+
+
+# ----------------------------------------------------
+# Release Targets
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_spec:
+
+release_docs_spec:
+
+release_tests_spec: tests
+ $(INSTALL_DIR) $(RELSYSDIR)
+ $(INSTALL_DATA) $(TEST_SPEC_FILE) $(ERL_FILES) $(RELSYSDIR)
+ @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
diff --git a/lib/jinterface/test/jinterface.dynspec b/lib/jinterface/test/jinterface.dynspec
new file mode 100644
index 0000000000..44712521df
--- /dev/null
+++ b/lib/jinterface/test/jinterface.dynspec
@@ -0,0 +1,32 @@
+%% -*- erlang -*-
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%% You can test this file using this command.
+%% file:script("jinterface.dynspec", [{'Os',"Unix"}]).
+
+case case code:priv_dir(jinterface) of
+ {error,bad_name} -> false;
+ P -> filelib:is_dir(P) end of
+ true ->
+ [];
+ false ->
+ NoApp = "No jinterface application",
+ [{skip,{nc_SUITE,NoApp}},
+ {skip,{jinterface_SUITE,NoApp}}]
+end.
diff --git a/lib/jinterface/test/jinterface_SUITE.erl b/lib/jinterface/test/jinterface_SUITE.erl
new file mode 100644
index 0000000000..ea097680dd
--- /dev/null
+++ b/lib/jinterface/test/jinterface_SUITE.erl
@@ -0,0 +1,761 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(jinterface_SUITE).
+
+-export([all/1, init_per_suite/1, end_per_suite/1,
+ init_per_testcase/2, end_per_testcase/2]).
+
+-export([nodename/1, register_and_whereis/1, get_names/1, boolean_atom/1,
+ node_ping/1, mbox_ping/1,
+ java_erlang_send_receive/1,
+ java_internal_send_receive_same_node/1,
+ java_internal_send_receive_different_nodes/1,
+ java_internal_send_receive_self/1,
+ java_link_and_exit/1, erl_link_and_exit/1,
+ erl_link_java_exit/1, java_link_erl_exit/1,
+ internal_link_linking_exits/1, internal_link_linked_exits/1,
+ internal_unlink_linking_exits/1, internal_unlink_linked_exits/1,
+ normal_exit/1, kill_mbox/1, kill_erl_proc_from_java/1,
+ kill_mbox_from_erlang/1, erl_exit_with_reason_any_term/1,
+ java_exit_with_reason_any_term/1,
+ status_handler_localStatus/1, status_handler_remoteStatus/1,
+ status_handler_connAttempt/1]).
+
+-include("test_server.hrl").
+-include("test_server_line.hrl").
+
+-define(debug,true).
+-ifdef(debug).
+-define(dbg(Str,Args), io:format(Str,Args)).
+-else.
+-define(dbg(Str,Args), ok).
+-endif.
+
+-define(link_test_reason,link_test_reason).
+
+%% Test cases in MboxSendReceive.java
+-define(java_erlang_send_receive,1).
+-define(java_internal_send_receive_same_node,2).
+-define(java_internal_send_receive_different_nodes,3).
+-define(java_internal_send_receive_self,4).
+
+%% Test cases in MboxLinkUnlink.java
+-define(java_link_and_exit, 1).
+-define(erl_link_and_exit, 2).
+-define(erl_link_java_exit, 3).
+-define(java_link_erl_exit, 4).
+-define(internal_link_linking_exits, 5).
+-define(internal_link_linked_exits, 6).
+-define(internal_unlink_linking_exits,7).
+-define(internal_unlink_linked_exits,8).
+-define(normal_exit,9).
+-define(kill_mbox,10).
+-define(kill_erl_proc_from_java,11).
+-define(kill_mbox_from_erlang,12).
+-define(erl_exit_with_reason_any_term,13).
+-define(java_exit_with_reason_any_term,14).
+
+
+%% Test cases in NodeStatusHandler.java
+-define(status_handler_localStatus,1).
+-define(status_handler_remoteStatus,2).
+-define(status_handler_connAttempt,3).
+
+%%%-----------------------------------------------------------------
+%%% INIT/END
+%%%-----------------------------------------------------------------
+all(suite) ->
+ lists:append([
+ fundamental(),
+ ping(),
+ send_receive(),
+ link_unlink(),
+ status_handler()
+ ]).
+
+fundamental() ->
+ [
+ nodename, % Nodename.java
+ register_and_whereis, % RegisterAndWhereis.java
+ get_names, % GetNames.java
+ boolean_atom % BooleanAtom.java
+ ].
+
+ping() ->
+ [
+ %% Implemented in NodePing.java
+ node_ping,
+
+ %% Implemented in MboxPing.java
+ mbox_ping
+ ].
+
+
+send_receive() ->
+ [
+ %% Implemented in MboxSendReceive.java
+ java_erlang_send_receive,
+ java_internal_send_receive_same_node,
+ java_internal_send_receive_different_nodes,
+ java_internal_send_receive_self
+ ].
+
+%% Note:
+%%
+%% The test cases in MboxLinkUnlink.java and in
+%% NodePing.java, all uses default cookie, and if there
+%% is a problem with having the same default cookie in
+%% erlang vs jinterface, e.g because the home directory
+%% does not get the same in some cases on Windows
+%% - they will all fail.
+
+link_unlink() ->
+ [
+ %% Implemented in MboxLinkUnlink.java
+ java_link_and_exit,
+ erl_link_and_exit,
+ erl_link_java_exit,
+ java_link_erl_exit,
+ internal_link_linking_exits,
+ internal_link_linked_exits,
+ internal_unlink_linking_exits,
+ internal_unlink_linked_exits,
+ normal_exit,
+ kill_mbox,
+ kill_erl_proc_from_java,
+ kill_mbox_from_erlang,
+ erl_exit_with_reason_any_term,
+ java_exit_with_reason_any_term
+ ].
+
+status_handler() ->
+ [
+ %% Implemented in NodeStatusHandler.java
+ status_handler_localStatus,
+ status_handler_remoteStatus,
+ status_handler_connAttempt
+ ].
+
+
+init_per_suite(Config) when is_list(Config) ->
+ jitu:init_all(Config).
+
+end_per_suite(Config) when is_list(Config) ->
+ jitu:finish_all(Config).
+
+init_per_testcase(_Case,Config) ->
+ Dog = ?t:timetrap({seconds,10}),
+ [{watch_dog,Dog}|Config].
+
+end_per_testcase(_Case,Config) ->
+ ?t:timetrap_cancel(?config(watch_dog,Config)),
+ ok.
+
+
+%%%-----------------------------------------------------------------
+%%% TEST CASES
+%%%-----------------------------------------------------------------
+nodename(doc) ->
+ ["Nodename.java: "
+ "Test OtpNode.node(), OtpNode.alive() and OtpNode.host()"];
+nodename(suite) ->
+ [];
+nodename(Config) when is_list(Config) ->
+ [_,Host] = string:tokens(atom_to_list(node()),"@"),
+ ok = jitu:java(?config(java, Config),
+ ?config(data_dir, Config),
+ "Nodename",
+ [list_to_atom(Host)]).
+
+%%%-----------------------------------------------------------------
+register_and_whereis(doc) ->
+ ["RegisterAndWhereis.java: "
+ "Test OtpNode.registerName(...), OtpMbox.registerName(...) and "
+ "OtpNode.whereis(...)"];
+register_and_whereis(suite) ->
+ [];
+register_and_whereis(Config) when is_list(Config) ->
+ ok = jitu:java(?config(java, Config),
+ ?config(data_dir, Config),
+ "RegisterAndWhereis",
+ []).
+
+%%%-----------------------------------------------------------------
+get_names(doc) ->
+ ["GetNames.java: "
+ "Test OtpNode.getNames()"];
+get_names(suite) ->
+ [];
+get_names(Config) when is_list(Config) ->
+ ok = jitu:java(?config(java, Config),
+ ?config(data_dir, Config),
+ "GetNames",
+ []).
+
+%%%-----------------------------------------------------------------
+boolean_atom(doc) ->
+ ["BooleanAtom.java: "
+ "Test OtpErlangAtom.booleanValue()"];
+boolean_atom(suite) ->
+ [];
+boolean_atom(Config) when is_list(Config) ->
+ ok = jitu:java(?config(java, Config),
+ ?config(data_dir, Config),
+ "BooleanAtom",
+ []).
+
+%%%-----------------------------------------------------------------
+node_ping(doc) ->
+ ["NodePing.java: "
+ "Test OtpNode.ping(java.lang.String node, long timeout)"];
+node_ping(suite) ->
+ [];
+node_ping(Config) when is_list(Config) ->
+ ok = jitu:java(?config(java, Config),
+ ?config(data_dir, Config),
+ "NodePing",
+ [erlang:get_cookie(),node()]).
+
+%%%-----------------------------------------------------------------
+mbox_ping(doc) ->
+ ["MboxPing.java: "
+ "Test OtpNode.createMbox(...) and OtpMbox.ping(...)"];
+mbox_ping(suite) ->
+ [];
+mbox_ping(Config) when is_list(Config) ->
+ ok = jitu:java(?config(java, Config),
+ ?config(data_dir, Config),
+ "MboxPing",
+ [erlang:get_cookie(),node()]).
+
+%%%-----------------------------------------------------------------
+java_erlang_send_receive(doc) ->
+ ["Test sending/receiving of erlang messages between erlang and java"];
+java_erlang_send_receive(suite) ->
+ [];
+java_erlang_send_receive(Config) when is_list(Config) ->
+ send_receive(?java_erlang_send_receive, fun echo_loop/0, Config).
+
+echo_loop() ->
+ receive
+ {From,Msg} ->
+ ?dbg("erl_send_receive_server received ~p",[{From,Msg}]),
+ ?dbg("erl_send_receive_server sending ~p",[Msg]),
+ From ! Msg,
+ echo_loop();
+ done ->
+ ok
+ end.
+
+
+%%%-----------------------------------------------------------------
+java_internal_send_receive_same_node(doc) ->
+ ["MboxSendReceive.java: "
+ "Test sending/receiving of erlang messages between mboxes "
+ "on the same java node."];
+java_internal_send_receive_same_node(suite) ->
+ [];
+java_internal_send_receive_same_node(Config) when is_list(Config) ->
+ send_receive(?java_internal_send_receive_same_node,
+ fun() -> receive done -> ok end end,
+ Config).
+
+%%%-----------------------------------------------------------------
+java_internal_send_receive_different_nodes(doc) ->
+ ["MboxSendReceive.java: "
+ "Test sending/receiving of erlang messages between mboxes "
+ "on different java nodes."];
+java_internal_send_receive_different_nodes(suite) ->
+ [];
+java_internal_send_receive_different_nodes(Config) when is_list(Config) ->
+ send_receive(?java_internal_send_receive_different_nodes,
+ fun() -> receive done -> ok end end,
+ Config).
+
+%%%-----------------------------------------------------------------
+java_internal_send_receive_self(doc) ->
+ ["MboxSendReceive.java: "
+ "Test sending/receiving of erlang messages from an mbox to itself"];
+java_internal_send_receive_self(suite) ->
+ [];
+java_internal_send_receive_self(Config) when is_list(Config) ->
+ send_receive(?java_internal_send_receive_self,
+ fun() -> receive done -> ok end end,
+ Config).
+
+%%%-----------------------------------------------------------------
+java_link_and_exit(doc) ->
+ ["MboxLinkUnlink.java: "
+ "Test link between erlang process and java mailbox."
+ "Java mailbox links and exits"];
+java_link_and_exit(suite) ->
+ [];
+java_link_and_exit(Config) when is_list(Config) ->
+ LinkFun =
+ fun(Mbox) ->
+ Mbox ! {?java_link_and_exit,self(),?link_test_reason},
+ receive after infinity -> ok end
+ end,
+ erl_java_link(LinkFun,java_link_and_exit,Config).
+
+
+%%%-----------------------------------------------------------------
+erl_link_and_exit(doc) ->
+ ["MboxLinkUnlink.java: "
+ "Test link between erlang process and java mailbox."
+ "Erlang process links and exits"];
+erl_link_and_exit(suite) ->
+ [];
+erl_link_and_exit(Config) when is_list(Config) ->
+ LinkFun = fun(Mbox) ->
+ link(Mbox),
+ Mbox ! {?erl_link_and_exit,self(),?link_test_reason},
+ receive ok -> ok end,
+ exit(?link_test_reason)
+ end,
+ erl_java_link(LinkFun,erl_link_and_exit,Config).
+
+%%%-----------------------------------------------------------------
+erl_link_java_exit(doc) ->
+ ["MboxLinkUnlink.java: "
+ "Test link between erlang process and java mailbox."
+ "Erlang process links and java mailbox exits"];
+erl_link_java_exit(suite) ->
+ [];
+erl_link_java_exit(Config) when is_list(Config) ->
+ LinkFun = fun(Mbox) ->
+ link(Mbox),
+ Mbox ! {?erl_link_java_exit,self(),?link_test_reason},
+ receive after infinity -> ok end
+ end,
+ erl_java_link(LinkFun,erl_link_java_exit,Config).
+
+
+%%%-----------------------------------------------------------------
+java_link_erl_exit(doc) ->
+ ["MboxLinkUnlink.java: "
+ "Test link between erlang process and java mailbox."
+ "Java mailbox links and erlang process exits"];
+java_link_erl_exit(suite) ->
+ [];
+java_link_erl_exit(Config) when is_list(Config) ->
+ LinkFun =
+ fun(Mbox) ->
+ Mbox ! {?java_link_erl_exit,self(),?link_test_reason},
+ receive ok -> ok end,
+ exit(?link_test_reason)
+ end,
+ erl_java_link(LinkFun,java_link_erl_exit,Config).
+
+%%%-----------------------------------------------------------------
+internal_link_linking_exits(doc) ->
+ ["MboxLinkUnlink.java: "
+ "Test link between two java mailboxes."
+ "The mailbox which creates the link is the one exiting"];
+internal_link_linking_exits(suite) ->
+ [];
+internal_link_linking_exits(Config) when is_list(Config) ->
+ internal_link_unlink(?internal_link_linking_exits,
+ internal_link_linking_exits,
+ Config).
+
+%%%-----------------------------------------------------------------
+internal_link_linked_exits(doc) ->
+ ["MboxLinkUnlink.java: "
+ "Test link between two java mailboxes."
+ "The mailbox which dies not create the link is the one exiting"];
+internal_link_linked_exits(suite) ->
+ [];
+internal_link_linked_exits(Config) when is_list(Config) ->
+ internal_link_unlink(?internal_link_linked_exits,
+ internal_link_linked_exits,
+ Config).
+
+%%%-----------------------------------------------------------------
+internal_unlink_linking_exits(doc) ->
+ ["MboxLinkUnlink.java: "
+ "Test link and unlink between two java mailboxes. "
+ "Mailbox1 creates a link to mailbox2 and removes it. "
+ "Then it creates another link and mailbox2 removes is. "
+ "Finally mailbox1 exits - mailbox2 must survive"];
+internal_unlink_linking_exits(suite) ->
+ [];
+internal_unlink_linking_exits(Config) when is_list(Config) ->
+ internal_link_unlink(?internal_unlink_linking_exits,
+ internal_unlink_linking_exits,
+ Config).
+
+%%%-----------------------------------------------------------------
+internal_unlink_linked_exits(doc) ->
+ ["MboxLinkUnlink.java: "
+ "Test link and unlink between two java mailboxes. "
+ "Mailbox1 creates a link to mailbox2 and removes it. "
+ "Then it creates another link and mailbox2 removes is. "
+ "Finally mailbox2 exits - mailbox1 must survive"];
+internal_unlink_linked_exits(suite) ->
+ [];
+internal_unlink_linked_exits(Config) when is_list(Config) ->
+ internal_link_unlink(?internal_unlink_linked_exits,
+ internal_unlink_linked_exits,
+ Config).
+
+%%%-----------------------------------------------------------------
+normal_exit(doc) ->
+ ["MboxLinkUnlink.java: "
+ "Test that mbox.close() uses exit reason 'normal', i.e. "
+ "that linked processes are not terminated."];
+normal_exit(suite) ->
+ [];
+normal_exit(Config) when is_list(Config) ->
+ Fun =
+ fun() ->
+ register(erl_link_server,self()),
+ process_flag(trap_exit,true),
+ receive
+ {Main,Mbox} when is_pid(Main), is_pid(Mbox) ->
+ ?dbg("Erlang sending \"~p\"",[normal_exit]),
+ link(Mbox),
+ Pid = spawn_link(fun() ->
+ link(Mbox),
+ Mbox ! {?normal_exit},
+ receive after infinity -> ok end
+ end),
+ receive
+ {'EXIT',Mbox,normal} ->
+ %% Make sure that we don't get the
+ %% exit signal from Pid, and Pid
+ %% should still be alive.
+ receive
+ {'EXIT',Pid,Reason} ->
+ ?dbg("Got unexpected exit signal: ~p",
+ [{'EXIT',Pid,Reason}]),
+ exit({unexpected,{'EXIT',Pid,Reason}})
+ after 500 ->
+ true = erlang:is_process_alive(Pid),
+ exit(Pid,kill)
+ end,
+ receive done -> Main ! done end
+ after 1000 ->
+ receive
+ Other ->
+ ?dbg("Got garbage when waiting for exit:"
+ " ~p", [Other]),
+ Main ! done,
+ exit({got_unexpected,Other})
+ after 0 ->
+ ok
+ end
+ end;
+ Other ->
+ ?dbg("Got garbage: ~p",[Other]),
+ exit(Other)
+ end
+ end,
+
+ spawn_link(Fun),
+ ok = jitu:java(?config(java, Config),
+ ?config(data_dir, Config),
+ "MboxLinkUnlink",
+ [erlang:get_cookie(),node()]).
+
+
+%%%-----------------------------------------------------------------
+kill_mbox(doc) ->
+ ["MboxLinkUnlink.java: "
+ "Test that mbox.exit(new OtpErlangAtom(\"kill\") causes linked "
+ "processes to exit with reason 'killed', which can be trapped."];
+kill_mbox(suite) ->
+ {skip, "Not yet implemented"};
+kill_mbox(Config) when is_list(Config) ->
+ Fun =
+ fun() ->
+ register(erl_link_server,self()),
+ process_flag(trap_exit,true),
+ receive
+ {Main,Mbox} when is_pid(Main), is_pid(Mbox) ->
+ ?dbg("Erlang sending \"~p\"",[kill_mbox]),
+ Pid = spawn_link(fun() ->
+ process_flag(trap_exit,true),
+ link(Mbox),
+ Mbox ! {?kill_mbox},
+ receive
+ {'EXIT',Mbox,killed} ->
+ exit(correct_reason);
+ {'EXIT',Mbox,R} ->
+ exit({faulty_reason,R})
+ end
+ end),
+ receive
+ {'EXIT',Pid,{faulty_reason,Reason}} ->
+ receive done -> Main ! done end,
+ exit({faulty_reason,Reason});
+ {'EXIT',Pid,im_killed} ->
+ receive done -> Main ! done end
+ after 1000 ->
+ receive
+ Other ->
+ ?dbg("Got garbage when waiting for exit:"
+ " ~p", [Other]),
+ Main ! done,
+ exit({got_unexpected,Other})
+ after 0 ->
+ ok
+ end
+ end;
+ Other ->
+ ?dbg("Got garbage: ~p",[Other]),
+ exit(Other)
+ end
+ end,
+
+ spawn_link(Fun),
+ ok = jitu:java(?config(java, Config),
+ ?config(data_dir, Config),
+ "MboxLinkUnlink",
+ [erlang:get_cookie(),node()]).
+
+%%%-----------------------------------------------------------------
+kill_erl_proc_from_java(doc) ->
+ ["MboxLinkUnlink.java: "
+ "Test that mbox.exit(pid, new OtpErlangAtom(\"kill\") causes erlang "
+ "processes <pid> to be killed, even if trapping exits"];
+kill_erl_proc_from_java(suite) ->
+ [];
+kill_erl_proc_from_java(Config) when is_list(Config) ->
+ LinkFun = fun(Mbox) ->
+ process_flag(trap_exit,true),
+ link(Mbox),
+ Mbox ! {?kill_erl_proc_from_java, self()},
+ receive after infinity -> ok end
+ end,
+ erl_java_link(LinkFun,kill_erl_proc_from_java,killed,Config).
+
+%%%-----------------------------------------------------------------
+kill_mbox_from_erlang(doc) ->
+ ["MboxLinkUnlink.java: "
+ "Test that exit(Mbox,kill) causes linked the Mbox to be killed, and"
+ "linked processes to exit with reason 'killed', even if trapping exits"];
+kill_mbox_from_erlang(suite) ->
+ {skip, "Not yet implemented"};
+kill_mbox_from_erlang(Config) when is_list(Config) ->
+ LinkFun = fun(Mbox) ->
+ link(Mbox),
+ Mbox ! {?kill_mbox_from_erlang},
+ exit(Mbox,kill),
+ receive after infinity -> ok end
+ end,
+ erl_java_link(LinkFun,kill_mbox_from_erlang,killed,Config).
+
+%%%-----------------------------------------------------------------
+erl_exit_with_reason_any_term(doc) ->
+ ["MboxLinkUnlink.java: "
+ "Test that any erlang term can be used as exit reason when erlang "
+ "process exits and is linked to an mbox."];
+erl_exit_with_reason_any_term(suite) ->
+ [];
+erl_exit_with_reason_any_term(Config) when is_list(Config) ->
+ Reason = [hei,self(),{this,is,"a",[different,"reason"]}],
+ LinkFun = fun(Mbox) ->
+ link(Mbox),
+ Mbox ! {?erl_exit_with_reason_any_term,self(),Reason},
+ receive ok -> ok end,
+ exit(Reason)
+ end,
+ erl_java_link(LinkFun,erl_exit_with_reason_any_term,Reason,Config).
+
+%%%-----------------------------------------------------------------
+java_exit_with_reason_any_term(doc) ->
+ ["MboxLinkUnlink.java: "
+ "Test that any erlang term can be used as exit reason when mbox "
+ "exits and is linked to an erlang process."];
+java_exit_with_reason_any_term(suite) ->
+ [];
+java_exit_with_reason_any_term(Config) when is_list(Config) ->
+ Reason = [hei,self(),{this,is,"a",[different,"reason"]}],
+ LinkFun =
+ fun(Mbox) ->
+ Mbox ! {?java_exit_with_reason_any_term,self(),Reason},
+ receive after infinity -> ok end
+ end,
+ erl_java_link(LinkFun,java_exit_with_reason_any_term,Reason,Config).
+
+
+%%%-----------------------------------------------------------------
+status_handler_localStatus(doc) ->
+ ["NodeStatusHandler.java: "
+ "Test OtpNode.registerStatusHandler(...) and the callback "
+ "OtpNodeStatus.localStatus(...)"];
+status_handler_localStatus(suite) ->
+ [];
+status_handler_localStatus(Config) when is_list(Config) ->
+ spawn_link(fun() ->
+ erl_status_server([{opt,{localStatus,"javanode1",true}},
+ {localStatus,"javanode1",false}])
+ end),
+ ok = jitu:java(?config(java, Config),
+ ?config(data_dir, Config),
+ "NodeStatusHandler",
+ [erlang:get_cookie(),node(),?status_handler_localStatus]).
+
+%%%-----------------------------------------------------------------
+status_handler_remoteStatus(doc) ->
+ ["NodeStatusHandler.java: "
+ "Test OtpNode.registerStatusHandler(...) and the callback "
+ "OtpNodeStatus.remoteStatus(...)"];
+status_handler_remoteStatus(suite) ->
+ [];
+status_handler_remoteStatus(Config) when is_list(Config) ->
+ spawn_link(fun() ->
+ erl_status_server([{opt,{localStatus,"javanode1",true}},
+ {remoteStatus,"javanode2",true},
+ {remoteStatus,"javanode2",false}])
+ end),
+ ok = jitu:java(?config(java, Config),
+ ?config(data_dir, Config),
+ "NodeStatusHandler",
+ [erlang:get_cookie(),node(),?status_handler_remoteStatus]).
+
+
+%%%-----------------------------------------------------------------
+status_handler_connAttempt(doc) ->
+ ["NodeStatusHandler.java: "
+ "Test OtpNode.registerStatusHandler(...) and the callback "
+ "OtpNodeStatus.connAttempt(...)"];
+status_handler_connAttempt(suite) ->
+ [];
+status_handler_connAttempt(Config) when is_list(Config) ->
+ spawn_link(fun() ->
+ erl_status_server([{opt,{localStatus,"javanode1",true}},
+ {connAttempt,"unknown",true},
+ {connAttempt,"javanode3",false}])
+ end),
+ ok = jitu:java(?config(java, Config),
+ ?config(data_dir, Config),
+ "NodeStatusHandler",
+ [erlang:get_cookie(),node(),?status_handler_connAttempt]).
+
+
+%%%-----------------------------------------------------------------
+%%% INTERNAL FUNCTIONS
+%%%-----------------------------------------------------------------
+send_receive(TestCaseTag,Fun,Config) ->
+ spawn(fun() ->
+ register(erl_send_receive_server,self()),
+ receive
+ From when is_pid(From) ->
+ JavaNode = node(From),
+ [JavaNode] = nodes(hidden),
+ From ! {TestCaseTag,self()},
+ Fun(),
+ unregister(erl_send_receive_server)
+ end
+ end),
+ ok = jitu:java(?config(java, Config),
+ ?config(data_dir, Config),
+ "MboxSendReceive",
+ [erlang:get_cookie(),node()]).
+
+
+internal_link_unlink(Tag,Msg,Config) ->
+ Fun =
+ fun() ->
+ register(erl_link_server,self()),
+ process_flag(trap_exit,true),
+ receive
+ {Main,Mbox} when is_pid(Main), is_pid(Mbox) ->
+ ?dbg("Erlang sending \"~p\"",[Msg]),
+ Mbox ! {Tag,self(),?link_test_reason},
+ receive done -> Main ! done end;
+ Other ->
+ ?dbg("Got garbage: ~p",[Other]),
+ exit(Other)
+ end
+ end,
+
+ spawn_link(Fun),
+ ok = jitu:java(?config(java, Config),
+ ?config(data_dir, Config),
+ "MboxLinkUnlink",
+ [erlang:get_cookie(),node()]).
+
+
+erl_java_link(LinkFun,Msg,Config) ->
+ erl_java_link(LinkFun,Msg,?link_test_reason,Config).
+
+erl_java_link(LinkFun,Msg,Reason,Config) ->
+ Fun =
+ fun() ->
+ register(erl_link_server,self()),
+ process_flag(trap_exit,true),
+ receive
+ {Main,Mbox} when is_pid(Mbox), is_pid(Mbox) ->
+ ?dbg("Erlang sending \"~p\"",[Msg]),
+ Pid = spawn_link(fun() -> LinkFun(Mbox) end),
+ receive
+ {'EXIT',Pid,Reason} ->
+ receive done -> Main ! done end
+ after 1000 ->
+ receive
+ Other ->
+ ?dbg("Got garbage when waiting for exit:"
+ " ~p", [Other]),
+ Main ! done,
+ exit({got_unexpected,Other})
+ after 0 ->
+ ok
+ end
+ end;
+ Other ->
+ ?dbg("Got garbage: ~p",[Other]),
+ exit(Other)
+ end
+ end,
+
+ spawn_link(Fun),
+ ok = jitu:java(?config(java, Config),
+ ?config(data_dir, Config),
+ "MboxLinkUnlink",
+ [erlang:get_cookie(),node()]).
+
+erl_status_server(List) ->
+ register(erl_status_server,self()),
+ erl_status_server(List,undefined).
+erl_status_server([{opt,{Tag,NodeName,Up}},{Tag2,NodeName2,Up2}|Rest],_) ->
+ receive
+ {Tag,Node,Up,From} = M ->
+ ?dbg("erl_status_server got: ~p",[M]),
+ true = lists:prefix(NodeName,Node),
+ erl_status_server([{Tag2,NodeName2,Up2}|Rest],From);
+ {Tag2,Node2,Up2,From2} = M2 ->
+ ?dbg("erl_status_server got: ~p",[M2]),
+ true = lists:prefix(NodeName2,Node2),
+ erl_status_server(Rest,From2)
+ end;
+erl_status_server([{Tag,NodeName,Up}|Rest],_) ->
+ receive
+ {Tag,Node,Up,From} = M ->
+ ?dbg("erl_status_server got: ~p",[M]),
+ true = lists:prefix(NodeName,Node),
+ erl_status_server(Rest,From);
+ Other ->
+ ?dbg("erl_status_server got garbage: ~p",[Other]),
+ exit(Other)
+ end;
+erl_status_server([],From) ->
+ From ! done.
diff --git a/lib/jinterface/test/jinterface_SUITE_data/BooleanAtom.java b/lib/jinterface/test/jinterface_SUITE_data/BooleanAtom.java
new file mode 100644
index 0000000000..9554d50c9f
--- /dev/null
+++ b/lib/jinterface/test/jinterface_SUITE_data/BooleanAtom.java
@@ -0,0 +1,46 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2004-2010. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+import com.ericsson.otp.erlang.*;
+
+class BooleanAtom {
+
+ /*
+ Implements test case jinterface_SUITE:boolean_atom/1
+
+ Test the function OtpErlangAtom.booleanValue()
+ */
+
+ public static void main(String argv[]) {
+
+ OtpErlangAtom atom = new OtpErlangAtom("true");
+ if (!atom.booleanValue()) fail(1);
+
+ atom = new OtpErlangAtom("false");
+ if (atom.booleanValue()) fail(2);
+
+ atom = new OtpErlangAtom("somethingelse");
+ if (atom.booleanValue()) fail(3);
+
+ }
+
+ private static void fail(int reason) {
+ System.exit(reason);
+ }
+}
diff --git a/lib/jinterface/test/jinterface_SUITE_data/GetNames.java b/lib/jinterface/test/jinterface_SUITE_data/GetNames.java
new file mode 100644
index 0000000000..3d2bc4ac84
--- /dev/null
+++ b/lib/jinterface/test/jinterface_SUITE_data/GetNames.java
@@ -0,0 +1,68 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2004-2010. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+import java.util.ArrayList;
+import com.ericsson.otp.erlang.*;
+
+class GetNames {
+
+ /*
+ Implements test case jinterface_SUITE:get_names/1
+
+ */
+
+ public static void main(String argv[]) {
+
+ try {
+ OtpNode node = new OtpNode("javanode");
+ OtpMbox mbox1 = node.createMbox();
+ mbox1.registerName("mbox1");
+ node.createMbox("mbox2");
+ OtpMbox mbox3 = node.createMbox();
+ node.registerName("mbox3",mbox3);
+
+ ArrayList existing_names = new ArrayList();
+ existing_names.add("mbox3");
+ existing_names.add("mbox2");
+ existing_names.add("mbox1");
+
+ String[] names = node.getNames();
+ if (names.length != existing_names.size()) fail(1);
+
+ for(int i=0; i<names.length; i++) {
+ System.out.println("" + names[i]);
+ existing_names.remove(names[i]);
+ }
+
+ if (!existing_names.isEmpty()) fail(2);
+ }
+ catch (Exception e) {
+ fail("" + e, 3);
+ }
+ }
+
+ private static void fail(int reason) {
+ System.exit(reason);
+ }
+
+ private static void fail(String str, int reason) {
+ System.out.println(str);
+ System.exit(reason);
+ }
+}
diff --git a/lib/jinterface/test/jinterface_SUITE_data/Makefile.src b/lib/jinterface/test/jinterface_SUITE_data/Makefile.src
new file mode 100644
index 0000000000..2a3dca463b
--- /dev/null
+++ b/lib/jinterface/test/jinterface_SUITE_data/Makefile.src
@@ -0,0 +1,62 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2004-2010. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+
+# Note: This file *must* work for both Unix and Windows
+#
+# We use both `rm' (Unix) and `del' (Windows) for removing files, but
+# with a `-' in front so that the error in not finding `rm' (`del') on
+# Windows (Unix) is ignored.
+#
+# VxWorks? XXX
+#
+
+.SUFFIXES:
+.SUFFIXES: .java
+
+
+JAVAC = @JAVAC@
+ERLC = erlc
+
+JINTERFACE_CLASSPATH = @jinterface_classpath@
+
+CLASSPATH = .@PS@$(JINTERFACE_CLASSPATH)@PS@
+
+JAVA_FILES = \
+ Nodename.java \
+ RegisterAndWhereis.java \
+ GetNames.java \
+ BooleanAtom.java \
+ NodePing.java \
+ MboxPing.java \
+ MboxSendReceive.java \
+ MboxLinkUnlink.java \
+ NodeStatusHandler.java
+
+CLASS_FILES = $(JAVA_FILES:.java=.class)
+
+all: $(CLASS_FILES)
+
+clean:
+ -rm -f $(CLASS_FILES)
+ -del /F /Q $(CLASS_FILES)
+
+$(CLASS_FILES) : $(JAVA_FILES)
+ $(JAVAC) -classpath $(CLASSPATH) $(JAVA_FILES)
+
+#
diff --git a/lib/jinterface/test/jinterface_SUITE_data/MboxLinkUnlink.java b/lib/jinterface/test/jinterface_SUITE_data/MboxLinkUnlink.java
new file mode 100644
index 0000000000..5d1d097cc8
--- /dev/null
+++ b/lib/jinterface/test/jinterface_SUITE_data/MboxLinkUnlink.java
@@ -0,0 +1,201 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2004-2010. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+import com.ericsson.otp.erlang.*;
+
+class MboxLinkUnlink {
+
+ /*
+ Implements test case jinterface_SUITE:mbox_link_unlink/1
+
+
+
+ */
+
+ private static final int java_link_and_exit = 1;
+ private static final int erl_link_and_exit = 2;
+ private static final int erl_link_java_exit = 3;
+ private static final int java_link_erl_exit = 4;
+ private static final int internal_link_linking_exits = 5;
+ private static final int internal_link_linked_exits = 6;
+ private static final int internal_unlink_linking_exits = 7;
+ private static final int internal_unlink_linked_exits = 8;
+ private static final int normal_exit = 9;
+ private static final int kill_mbox = 10;
+ private static final int kill_erl_proc_from_java = 11;
+ private static final int kill_mbox_from_erlang = 12;
+ private static final int erl_exit_with_reason_any_term = 13;
+ private static final int java_exit_with_reason_any_term = 14;
+
+ private static boolean dbg = true;
+
+
+ public static void main(String argv[]) {
+
+
+ //String cookie = argv[0];
+ String erlNode = argv[1];
+ OtpErlangObject expected = null;
+ boolean waiting = false;
+
+ try { //
+ OtpNode node = new OtpNode("javanode");
+ OtpMbox mainMbox = node.createMbox();
+
+ try {
+ // Initiate and set up connection to erlang process
+ OtpMbox mbox = node.createMbox();
+ OtpMbox mbox2;
+
+ OtpErlangObject[] msg = {mainMbox.self(),mbox.self()};
+ mbox.send("erl_link_server", erlNode, new OtpErlangTuple(msg));
+ OtpErlangObject o = mbox.receive(1000);
+ if (o == null) System.exit(1);
+ OtpErlangTuple tuple = (OtpErlangTuple)o;
+ int tag = (int)((OtpErlangLong)tuple.elementAt(0)).longValue();
+
+ switch (tag) {
+
+ case java_exit_with_reason_any_term:
+ case java_link_and_exit:
+ dbg("Java got \"java_link_and_exit\" or " +
+ "\"java_exit_with_reason_any_term\"");
+ mbox.link((OtpErlangPid)tuple.elementAt(1));
+ mbox.send((OtpErlangPid)tuple.elementAt(1),
+ new OtpErlangAtom("ok"));
+ mbox.exit(tuple.elementAt(2));
+ break;
+ case erl_exit_with_reason_any_term:
+ case erl_link_and_exit:
+ dbg("Java got \"erl_link_and_exit\" or " +
+ "\"erl_exit_with_reason_any_term\"");
+ mbox.send((OtpErlangPid)tuple.elementAt(1),
+ new OtpErlangAtom("ok"));
+ waiting = true;
+ expected = tuple.elementAt(2);
+ mbox.receive(1000);
+ System.exit(2);
+ case erl_link_java_exit:
+ dbg("Java got \"erl_link_java_exit\"");
+ mbox.exit(tuple.elementAt(2));
+ break;
+ case java_link_erl_exit:
+ dbg("Java got \"java_link_erl_exit\"");
+ mbox.link((OtpErlangPid)tuple.elementAt(1));
+ mbox.send((OtpErlangPid)tuple.elementAt(1),
+ new OtpErlangAtom("ok"));
+ waiting = true;
+ expected = tuple.elementAt(2);
+ mbox.receive(1000);
+ System.exit(3);
+ case internal_link_linking_exits:
+ dbg("Java got \"internal_link_linking_exits\"");
+ mbox2 = node.createMbox();
+ mbox.link(mbox2.self());
+ mbox.exit(tuple.elementAt(2));
+ waiting = true;
+ expected = tuple.elementAt(2);
+ mbox2.receive(1000); // hanging waiting for exit
+ System.exit(4); // got someting other than exit
+ case internal_link_linked_exits:
+ dbg("Java got \"internal_link_linked_exits\"");
+ mbox2 = node.createMbox();
+ mbox.link(mbox2.self());
+ mbox2.exit(tuple.elementAt(2));
+ waiting = true;
+ expected = tuple.elementAt(2);
+ mbox.receive(1000); // hanging waiting for exit
+ System.exit(5); // got someting other than exit
+ case internal_unlink_linking_exits:
+ dbg("Java got \"internal_unlink_linking_exits\"");
+ mbox2 = node.createMbox();
+ mbox.link(mbox2.self());
+ mbox.unlink(mbox2.self());
+ mbox.link(mbox2.self());
+ mbox2.unlink(mbox.self());
+ mbox2.exit(tuple.elementAt(2));
+ if (mbox.receive(500)!=null) System.exit(6);
+ break;
+ case internal_unlink_linked_exits:
+ dbg("Java got \"internal_unlink_linked_exits\"");
+ mbox2 = node.createMbox();
+ mbox.link(mbox2.self());
+ mbox.unlink(mbox2.self());
+ mbox.link(mbox2.self());
+ mbox2.unlink(mbox.self());
+ mbox.exit(tuple.elementAt(2));
+ if (mbox2.receive(500)!=null) System.exit(7);
+ break;
+ case normal_exit:
+ dbg("Java got \"normal_exit\"");
+ mbox.close();
+ break;
+ case kill_mbox:
+ dbg("Java got \"kill_mbox\"");
+ mbox.exit("kill");
+ break;
+ case kill_erl_proc_from_java:
+ dbg("Java got \"kill_erl_proc_from_java\"");
+ mbox.exit((OtpErlangPid)tuple.elementAt(1),"kill");
+ break;
+ case kill_mbox_from_erlang:
+ dbg("Java got \"kill_mbox_from_erlang\"");
+ /* This will make the testcase successful, but it is
+ not the correct way to do it...
+ Mbox should probably just die when the kill signal is
+ received from erlang (or other mbox).
+
+ try {
+ mbox.receive(1000);
+ System.exit(8);
+ }
+ catch (OtpErlangExit exit) {
+ if(!(exit.reason().equals(new OtpErlangAtom("kill"))))
+ System.exit(9);
+ mbox.exit("killed");
+ }
+ */
+ break;
+ }
+ }
+ catch (OtpErlangExit exit) {
+ dbg("Java got exit: " + exit.reason());
+ if(!(waiting && exit.reason().equals(expected)))
+ System.exit(10);
+ }
+
+ OtpErlangAtom done = new OtpErlangAtom("done");
+ mainMbox.send("erl_link_server", erlNode, done);
+ OtpErlangObject o = mainMbox.receive(1000);
+ if (o == null) System.exit(11);
+ else if (!((OtpErlangAtom)o).equals(done))
+ System.exit(12);
+
+ }
+ catch (Exception e) {
+ System.out.println("EXCEPTION: " + e);
+ System.exit(13);
+ }
+ }
+
+ private static void dbg(String str) {
+ if (dbg) System.out.println(str);
+ }
+
+}
diff --git a/lib/jinterface/test/jinterface_SUITE_data/MboxPing.java b/lib/jinterface/test/jinterface_SUITE_data/MboxPing.java
new file mode 100644
index 0000000000..3a8497028e
--- /dev/null
+++ b/lib/jinterface/test/jinterface_SUITE_data/MboxPing.java
@@ -0,0 +1,50 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2004-2010. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+import com.ericsson.otp.erlang.*;
+
+class MboxPing {
+
+ /*
+ Implements test case jinterface_SUITE:mbox_ping/1
+
+ Creates an OtpNode object with an OtpMbox object. The test_server
+ node is pinged from the OtpMbox.
+ */
+
+ public static void main(String argv[]) {
+
+ try {
+ OtpNode node = new OtpNode("javanode",argv[0]);
+ OtpMbox mbox = node.createMbox();
+ if (mbox.ping(argv[1],2000)) {
+ System.out.println("OtpMbox.ping(" + argv[1] + ") -> true");
+ }
+ else {
+ System.out.println("ERROR: OtpMbox.ping(" + argv[1] +
+ ") -> false");
+ System.exit(1);
+ }
+ }
+ catch (Exception e) {
+ System.out.println("" + e);
+ System.exit(2);
+ }
+ }
+}
diff --git a/lib/jinterface/test/jinterface_SUITE_data/MboxSendReceive.java b/lib/jinterface/test/jinterface_SUITE_data/MboxSendReceive.java
new file mode 100644
index 0000000000..2db71bb5cd
--- /dev/null
+++ b/lib/jinterface/test/jinterface_SUITE_data/MboxSendReceive.java
@@ -0,0 +1,229 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2004-2010. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+import com.ericsson.otp.erlang.*;
+
+class MboxSendReceive {
+
+ /*
+ Implements test case jinterface_SUITE:mbox_send_receive/1
+
+ Test OtpMbox.send(...) and OtpMbox.receive(...)
+ */
+
+ private static final boolean dbg = true;
+ private static final int recTime = 2000;
+
+ private static final int java_erlang_send_receive = 1;
+ private static final int java_internal_send_receive_same_node = 2;
+ private static final int java_internal_send_receive_different_nodes = 3;
+ private static final int java_internal_send_receive_self = 4;
+
+ public static void main(String argv[]) {
+
+ String cookie = argv[0];
+ String erlNode = argv[1];
+
+ OtpErlangObject[] msgArray = new OtpErlangObject[2];
+ msgArray[1] = new OtpErlangAtom("hello world");
+ OtpErlangTuple msg = null;
+
+ try {
+ // Initiate: create javanode and mboxes
+ OtpNode node = new OtpNode("javanode",cookie);
+ OtpMbox mbox = node.createMbox();
+ OtpMbox mbox2 = node.createMbox("java_echo_server2");
+
+ // Send the pid of mbox to erlang and wait for test case
+ // instruction: {TestCaseTag, Pid}
+ mbox.send("erl_send_receive_server", erlNode, mbox.self());
+ OtpErlangObject o = mbox.receive(recTime);
+ if (o == null) System.exit(1);
+ OtpErlangTuple testCase = (OtpErlangTuple)o;
+ dbg("mbox received " + testCase);
+ int tag = (int)((OtpErlangLong)testCase.elementAt(0)).longValue();
+ OtpErlangPid erlangPid = (OtpErlangPid)testCase.elementAt(1);
+
+ switch (tag) {
+
+ case java_erlang_send_receive:
+
+ // Test1 (happened during initiation):
+ // Send mbox pid to erlang process with registered name.
+ // Erlang process sent back its pid to the mbox pid.
+
+ // Test2: Register name and sent it to the erlang pid. Erlang
+ // process shall send message back to my registered name.
+
+ mbox.registerName("java_echo_server");
+ msgArray[0] = getNameNode("java_echo_server",node);
+ msg = new OtpErlangTuple(msgArray);
+
+ dbg("java_echo_server sending " + msg);
+ mbox.send(erlangPid,msg);
+
+ o = mbox.receive(recTime);
+ dbg("java_echo_server received " + o);
+ if (o == null) System.exit(2);
+ if (!((OtpErlangAtom)o).equals(msgArray[1])) System.exit(3);
+
+ // Test3: Same as Test2, but using a new mbox2 which
+ // got its name already when it is created - i.e. not
+ // using mbox.registerName
+ msgArray[0] = getNameNode("java_echo_server2",node);
+ msg = new OtpErlangTuple(msgArray);
+
+ dbg("java_echo_server2 sending " + msg);
+ mbox2.send(erlangPid,msg);
+
+ o = mbox2.receive(recTime);
+ dbg("java_echo_server received " + o);
+ if (o == null) System.exit(4);
+ if (!((OtpErlangAtom)o).equals(msgArray[1])) System.exit(5);
+
+ break;
+
+ case java_internal_send_receive_same_node:
+
+ // Test1: Sending message between mboxes on same node
+ // given registered name and node without host.
+ mbox.send("java_echo_server2","javanode",msgArray[1]);
+ o = mbox2.receive(recTime);
+ dbg("Mbox at same node: " + o);
+ if (o == null) System.exit(6);
+ if(!((OtpErlangAtom)o).equals(msgArray[1])) System.exit(7);
+
+ // Test2: Sending message between mboxes on same node
+ // given registered name and node with host.
+ mbox.send("java_echo_server2",mbox2.self().node(),msgArray[1]);
+ o = mbox2.receive(recTime);
+ dbg("Mbox at same node: " + o);
+ if (o == null) System.exit(8);
+ if(!((OtpErlangAtom)o).equals(msgArray[1])) System.exit(9);
+
+ // Test3: Sending message between mboxes on same node
+ // given registered name but not node.
+ mbox.send("java_echo_server2",msgArray[1]);
+ o = mbox2.receive(recTime);
+ dbg("Mbox at same node: " + o);
+ if (o == null) System.exit(10);
+ if(!((OtpErlangAtom)o).equals(msgArray[1])) System.exit(11);
+
+ // Test4: Sending message between mboxes on same node
+ // given pid.
+ mbox.send(mbox2.self(),msgArray[1]);
+ o = mbox2.receive(recTime);
+ dbg("Mbox at same node: " + o);
+ if (o == null) System.exit(12);
+ if(!((OtpErlangAtom)o).equals(msgArray[1])) System.exit(13);
+
+ break;
+
+ case java_internal_send_receive_different_nodes:
+
+ OtpNode node2 = new OtpNode("javanode2", cookie);
+ OtpMbox mboxOtherNode = node2.createMbox("mboxOtherNode");
+
+ // Test1: Sending message between mboxes on different
+ // nodes given registered name and node without host.
+ mbox.send("mboxOtherNode","javanode2",msgArray[1]);
+ o = mboxOtherNode.receive(recTime);
+ dbg("Mbox at same node: " + o);
+ if (o == null) System.exit(14);
+ if(!((OtpErlangAtom)o).equals(msgArray[1])) System.exit(15);
+
+ // Test2: Sending message between mboxes on different
+ // nodes given registered name and node with host.
+ mbox.send("mboxOtherNode",mboxOtherNode.self().node(),
+ msgArray[1]);
+ o = mboxOtherNode.receive(recTime);
+ dbg("Mbox at same node: " + o);
+ if (o == null) System.exit(16);
+ if(!((OtpErlangAtom)o).equals(msgArray[1])) System.exit(17);
+
+ // Test3: Sending message between mboxes on different
+ // nodes given pid.
+ mbox.send(mboxOtherNode.self(),msgArray[1]);
+ o = mboxOtherNode.receive(recTime);
+ dbg("Mbox at same node: " + o);
+ if (o == null) System.exit(18);
+ if(!((OtpErlangAtom)o).equals(msgArray[1])) System.exit(19);
+
+ break;
+
+
+ case java_internal_send_receive_self:
+
+ // Test1: Sending message to myself given registered
+ // name and node without host.
+ mbox2.send("java_echo_server2","javanode",msgArray[1]);
+ o = mbox2.receive(recTime);
+ dbg("Self: " + o);
+ if (o == null) System.exit(18);
+ if(!((OtpErlangAtom)o).equals(msgArray[1])) System.exit(19);
+
+ // Test2: Sending message to myself given registered
+ // name and node with host.
+ mbox2.send("java_echo_server2",mbox2.self().node(),msgArray[1]);
+ o = mbox2.receive(recTime);
+ dbg("Self: " + o);
+ if (o == null) System.exit(20);
+ if(!((OtpErlangAtom)o).equals(msgArray[1])) System.exit(21);
+
+ // Test3: Sending message to myself given registered
+ // name but not host.
+ mbox2.send("java_echo_server2",msgArray[1]);
+ o = mbox2.receive(recTime);
+ dbg("Self: " + o);
+ if (o == null) System.exit(22);
+ if(!((OtpErlangAtom)o).equals(msgArray[1])) System.exit(23);
+
+ // Test4: Sending message to myself given pid.
+ mbox2.send(mbox2.self(),msgArray[1]);
+ o = mbox2.receive(recTime);
+ dbg("Self: " + o);
+ if (o == null) System.exit(24);
+ if(!((OtpErlangAtom)o).equals(msgArray[1])) System.exit(25);
+
+ break;
+
+ }
+
+ // Closing erl_send_receive_server by sending the atom 'done' to it.
+ mbox.send(erlangPid,new OtpErlangAtom("done"));
+ }
+ catch (Exception e) {
+ System.out.println("" + e);
+ System.exit(26);
+ }
+ }
+
+ private static OtpErlangTuple getNameNode(String mboxName,OtpNode node) {
+ OtpErlangObject[] array = {new OtpErlangAtom(mboxName),
+ new OtpErlangAtom(node.node())};
+ return new OtpErlangTuple(array);
+
+ }
+
+ private static void dbg(String str) {
+ if (dbg) System.out.println(str);
+ }
+
+
+}
diff --git a/lib/jinterface/test/jinterface_SUITE_data/NodePing.java b/lib/jinterface/test/jinterface_SUITE_data/NodePing.java
new file mode 100644
index 0000000000..d0df5c46b5
--- /dev/null
+++ b/lib/jinterface/test/jinterface_SUITE_data/NodePing.java
@@ -0,0 +1,83 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2004-2010. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+import com.ericsson.otp.erlang.*;
+
+class NodePing {
+
+ /*
+ Implements test case jinterface_SUITE:node_ping/1
+
+ Creates three OtpNode objects. One with default cookie, one with
+ specified same cookie as the node running the test case and one
+ with a faulty cookie. From each OtpNode object the test_server
+ node is pinged.
+
+ Also the default cookie node pings itself, and the node with the
+ specified cookie pings the node with default cookie.
+ */
+
+ public static void main(String argv[]) {
+
+ String cookie = argv[0];
+ String erlNode = argv[1];
+
+ try {
+ OtpNode node1 = new OtpNode("javanode1");
+ ping(node1,erlNode,"Default cookie:",true,1);
+ ping(node1,node1.node(),"Self:",true,2);
+ ping(node1,"javanode1","Self:",true,3);
+
+ OtpNode node2 = new OtpNode("javanode2",cookie);
+ ping(node2,erlNode,"Specified cookie:",true,4);
+ ping(node2,"javanode1","Javanode (no host):",true,5);
+ ping(node2,node1.node(),"Javanode:",true,6);
+
+ OtpNode node3 = new OtpNode("javanode3","faultycookie");
+ ping(node3,erlNode,"Faulty cookie:",false,7);
+
+ // Test OtpNode.cookie() and OtpNode.setCookie(cookie) as well
+ if (!node3.cookie().equals("faultycookie"))
+ fail("Testing OtpNode.cookie()",8);
+ String old = node3.setCookie(cookie);
+ if (!old.equals("faultycookie"))
+ fail("Checking return of OtpNode.setCookie(cookie)",9);
+ ping(node3,erlNode,"setCookie:",true,10);
+ }
+ catch (Exception e) {
+ fail("" + e, 11);
+ }
+ }
+
+ private static void ping(OtpNode node, String remote, String descr,
+ boolean expected, int reason) {
+ if ( node.ping(remote,2000) == expected ) {
+ System.out.println(descr + " ping(" + remote + ") -> " + expected);
+ }
+ else {
+ fail("ERROR: " + descr + " ping(" + remote +") -> " + !expected,
+ reason);
+ }
+ }
+
+ private static void fail(String str, int reason) {
+ System.out.println(str);
+ System.exit(reason);
+ }
+}
diff --git a/lib/jinterface/test/jinterface_SUITE_data/NodeStatusHandler.java b/lib/jinterface/test/jinterface_SUITE_data/NodeStatusHandler.java
new file mode 100644
index 0000000000..51ea15b5ef
--- /dev/null
+++ b/lib/jinterface/test/jinterface_SUITE_data/NodeStatusHandler.java
@@ -0,0 +1,168 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2004-2010. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+import com.ericsson.otp.erlang.*;
+
+public class NodeStatusHandler extends OtpNodeStatus {
+ /*
+ Implements java side of test cases in jinterface_SUITE.erl
+
+ Test OtpNode.registerStatusHandler(...) and class OtpNodeStatus.
+ */
+
+ private static final boolean dbg = true;
+ private static final int recTime = 2000;
+
+ private static String erlNode = null;
+ private static String cookie = null;
+ private static OtpMbox mbox = null;
+
+ private static final int status_handler_localStatus = 1;
+ private static final int status_handler_remoteStatus = 2;
+ private static final int status_handler_connAttempt = 3;
+
+ public static void main(String argv[]) {
+
+ cookie = argv[0];
+ erlNode = argv[1];
+
+ try {
+ OtpNode javaNode = new OtpNode("javanode", cookie);
+ mbox = javaNode.createMbox();
+ }
+ catch (Exception e) {
+ dbg("EXCEPTION when creating javanode: " + e);
+ System.exit(1);
+ }
+
+ try {
+ OtpNode node1 = new OtpNode("javanode1", cookie);
+ node1.registerStatusHandler(new NodeStatusHandler());
+
+ switch (Integer.parseInt(argv[2])) {
+
+ case status_handler_localStatus:
+ dbg("java running test case \"status_handler_localStatus\"");
+
+ Thread.sleep(200); // Give 'nodeup' message a chance
+ // before closing
+ node1.close();
+ Thread.sleep(500);
+ break;
+
+ case status_handler_remoteStatus:
+ dbg("java running test case \"status_handler_remoteStatus\"");
+
+ OtpNode node2 = new OtpNode("javanode2", cookie);
+ node2.ping(node1.node(),2000);
+ node2.close();
+ Thread.sleep(500);
+ break;
+
+ case status_handler_connAttempt:
+ dbg("java running test case \"status_handler_connAttempt\"");
+
+ OtpNode node3 = new OtpNode("javanode3","othercookie");
+ node3.ping(node1.node(),2000);
+ node1.ping(node3.node(),2000);
+ break;
+
+ }
+
+ OtpErlangObject o = mbox.receive(recTime);
+ if (o == null) System.exit(2);
+ if (! ((OtpErlangAtom)o).atomValue().equals("done"))
+ System.exit(3);
+
+ }
+ catch (Exception e) {
+ dbg("EXCEPTION: " + e);
+ System.exit(4);
+ }
+
+ }
+
+
+
+ public void remoteStatus(String node, boolean up, Object info) {
+ try {
+ dbg("Got remoteStatus: " + node + " " + up + " " + info);
+ OtpErlangObject[] msgArray = new OtpErlangObject[4];
+ msgArray[0] = new OtpErlangAtom("remoteStatus");
+ msgArray[1] = new OtpErlangString(node);
+ msgArray[2] = new OtpErlangBoolean(up);
+ msgArray[3] = mbox.self();
+ OtpErlangTuple msg = new OtpErlangTuple(msgArray);
+ mbox.send("erl_status_server", erlNode, msg);
+
+ }
+ catch (Exception e) {
+ dbg("EXCEPTION in remoteStatus: " + e + "\nArgs: " +
+ node + " " + up + " " + info);
+ System.exit(5);
+ }
+ }
+
+
+ public void localStatus(String node, boolean up, Object info) {
+ try {
+ dbg("Got localStatus: " + node + " " + up + " " + info);
+ OtpErlangObject[] msgArray = new OtpErlangObject[4];
+ msgArray[0] = new OtpErlangAtom("localStatus");
+ msgArray[1] = new OtpErlangString(node);
+ msgArray[2] = new OtpErlangBoolean(up);
+ msgArray[3] = mbox.self();
+ OtpErlangTuple msg = new OtpErlangTuple(msgArray);
+ mbox.send("erl_status_server", erlNode, msg);
+
+ }
+ catch (Exception e) {
+ dbg("EXCEPTION in localStatus: " + e + "\nArgs: " +
+ node + " " + up + " " + info);
+ System.exit(6);
+ }
+ }
+
+
+
+ public void connAttempt(String node, boolean incoming, Object info) {
+ try {
+ dbg("Got connAttempt: " + node + " " + incoming + " " + info);
+ OtpErlangObject[] msgArray = new OtpErlangObject[4];
+ msgArray[0] = new OtpErlangAtom("connAttempt");
+ msgArray[1] = new OtpErlangString(node);
+ msgArray[2] = new OtpErlangBoolean(incoming);
+ msgArray[3] = mbox.self();
+ OtpErlangTuple msg = new OtpErlangTuple(msgArray);
+ mbox.send("erl_status_server", erlNode, msg);
+
+ }
+ catch (Exception e) {
+ dbg("EXCEPTION in connAttempt: " + e + "\nArgs: " +
+ node + " " + incoming + " " + info);
+ System.exit(7);
+ }
+ }
+
+
+ private static void dbg(String str) {
+ if (dbg) System.out.println(str);
+ }
+
+}
diff --git a/lib/jinterface/test/jinterface_SUITE_data/Nodename.java b/lib/jinterface/test/jinterface_SUITE_data/Nodename.java
new file mode 100644
index 0000000000..dc8cb9c49f
--- /dev/null
+++ b/lib/jinterface/test/jinterface_SUITE_data/Nodename.java
@@ -0,0 +1,54 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2004-2010. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+import com.ericsson.otp.erlang.*;
+
+class Nodename {
+
+ /*
+ Implements test case jinterface_SUITE:nodename/1
+
+ */
+
+ public static void main(String argv[]) {
+
+ String host = argv[0];
+
+ try {
+ OtpNode node = new OtpNode("javanode");
+ System.out.println("Given host: " + host +
+ " Host: " + node.host() +
+ " Alive: " + node.alive() +
+ " Node: " + node.node());
+
+ if (!node.host().equals(host)) fail(1);
+ if (!node.alive().equals("javanode")) fail(2);
+ if (!node.node().equals("javanode@" + host)) fail(3);
+ }
+ catch (Exception e) {
+ System.out.println("" + e);
+ fail(4);
+ }
+ }
+
+ private static void fail(int reason) {
+ System.exit(reason);
+ }
+
+}
diff --git a/lib/jinterface/test/jinterface_SUITE_data/RegisterAndWhereis.java b/lib/jinterface/test/jinterface_SUITE_data/RegisterAndWhereis.java
new file mode 100644
index 0000000000..9df01981b2
--- /dev/null
+++ b/lib/jinterface/test/jinterface_SUITE_data/RegisterAndWhereis.java
@@ -0,0 +1,79 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2004-2010. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+import com.ericsson.otp.erlang.*;
+
+class RegisterAndWhereis {
+
+ /*
+ Implements test case jinterface_SUITE:register_and_whereis/1
+
+ */
+
+ public static void main(String argv[]) {
+
+ try {
+ OtpNode node = new OtpNode("javanode");
+ OtpMbox mbox1 = node.createMbox();
+ mbox1.registerName("mbox1");
+ OtpMbox mbox2 = node.createMbox("mbox2");
+ OtpMbox mbox3 = node.createMbox();
+ node.registerName("mbox3",mbox3);
+
+ OtpErlangPid pid1 = mbox1.self();
+ OtpErlangPid pid2 = mbox2.self();
+ OtpErlangPid pid3 = mbox3.self();
+
+ if (!pid1.equals(node.whereis("mbox1"))) fail(1);
+ if (!pid1.equals(mbox1.whereis("mbox1"))) fail(2);
+ if (!pid1.equals(mbox2.whereis("mbox1"))) fail(3);
+ if (!pid1.equals(mbox3.whereis("mbox1"))) fail(4);
+ if (!pid2.equals(node.whereis("mbox2"))) fail(5);
+ if (!pid2.equals(mbox2.whereis("mbox2"))) fail(6);
+ if (!pid3.equals(node.whereis("mbox3"))) fail(7);
+ if (!pid3.equals(mbox3.whereis("mbox3"))) fail(8);
+
+ node.closeMbox(mbox1);
+ mbox2.close();
+
+ if (node.whereis("mbox1") != null) fail(9);
+ if (node.whereis("mbox2") != null) fail(10);
+ if (mbox3.whereis("mbox1") != null) fail(11);
+ if (mbox3.whereis("mbox2") != null) fail(12);
+
+ mbox3.close();
+ if (mbox2.whereis("mbox3") != null) fail(13);
+
+
+
+ }
+ catch (Exception e) {
+ fail("" + e, 14);
+ }
+ }
+
+ private static void fail(int reason) {
+ System.exit(reason);
+ }
+
+ private static void fail(String str, int reason) {
+ System.out.println(str);
+ System.exit(reason);
+ }
+}
diff --git a/lib/jinterface/test/jitu.erl b/lib/jinterface/test/jitu.erl
new file mode 100644
index 0000000000..c57fb9bfad
--- /dev/null
+++ b/lib/jinterface/test/jitu.erl
@@ -0,0 +1,156 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%----------------------------------------------------------------------
+%% JInterface Test Utils
+%%----------------------------------------------------------------------
+-module(jitu).
+
+
+-export([java/3,
+ java/4,
+ java/5,
+ init_all/1,
+ finish_all/1]).
+
+%%
+%% Lots of stuff here are originating from java_client_erl_server_SUITE.erl
+%% (ic) ...
+%%
+
+
+
+java(Java, Dir, ClassAndArgs) ->
+ cmd(Java++" -classpath "++classpath(Dir)++" "++ClassAndArgs).
+
+java(Java, Dir, Class, Args) ->
+ java(Java, Dir, Class++" "++to_string(Args)).
+
+java(Java, Dir, Class, Args, Props) ->
+ java(Java, Dir, Props++" "++Class, Args).
+
+
+
+
+init_all(Config) when list(Config) ->
+ case find_executable(["java"]) of
+ false -> {skip,"Found no Java VM"};
+ Path -> [{java,Path}|Config]
+ end.
+
+finish_all(Config) -> Config.
+
+%%
+%% Internal stuff...
+%%
+
+
+find_executable([]) ->
+ false;
+find_executable([E|T]) ->
+ case os:find_executable(E) of
+ false -> find_executable(T);
+ Path -> Path
+ end.
+
+to_string([H|T]) when integer(H) ->
+ integer_to_list(H)++" "++to_string(T);
+to_string([H|T]) when atom(H) ->
+ atom_to_list(H)++" "++to_string(T);
+to_string([H|T]) when pid(H) ->
+ pid_to_list(H)++" "++to_string(T);
+to_string([H|T]) when list(H) ->
+ lists:flatten(H)++" "++to_string(T);
+to_string([]) -> [].
+
+% javac(Dir, File) ->
+% cmd("javac -d "++Dir++" -classpath "++classpath(Dir)++" "++
+% filename:join(Dir, File)).
+
+classpath(Dir) ->
+ PS =
+ case os:type() of
+ {win32, _} -> ";";
+ _ -> ":"
+ end,
+ Dir++PS++
+ filename:join([code:lib_dir(jinterface),"priv","OtpErlang.jar"])++PS++
+ case os:getenv("CLASSPATH") of
+ false -> "";
+ Classpath -> Classpath
+ end.
+
+
+cmd(Cmd) ->
+ PortOpts = [{line,80},eof,exit_status,stderr_to_stdout],
+ io:format("cmd: ~s~n", [Cmd]),
+ case catch open_port({spawn,Cmd}, PortOpts) of
+ Port when port(Port) ->
+ Result = cmd_loop(Port, []),
+ io:format("cmd res: ~w~n", [Result]),
+ case Result of
+ 0 -> ok;
+ ExitCode when integer(ExitCode) -> {error,ExitCode};
+ Error -> Error
+ end;
+ {'EXIT',Reason} ->
+ {error,Reason}
+ end.
+
+cmd_loop(Port, Line) ->
+ receive
+ {Port,eof} ->
+ receive
+ {Port,{exit_status,ExitStatus}} ->
+ ExitStatus
+ after 1 ->
+ undefined
+ end;
+ {Port,{exit_status,ExitStatus}} ->
+ receive
+ {Port,eof} ->
+ ok after 1 -> ok end,
+ ExitStatus;
+ {Port,{data,{Tag,Data}}} ->
+ case Tag of
+ eol ->
+ io:put_chars([Line|cr_to_nl(Data)]),
+ io:nl(),
+ cmd_loop(Port, []);
+ noeol ->
+ cmd_loop(Port, [Line|cr_to_nl(Data)])
+ end;
+ {'EXIT',Port,Reason} ->
+ {error,Reason};
+ Other ->
+ io:format("WARNING: Unexpected at ~s:~p: ~p~n",
+ [?MODULE_STRING,?LINE,Other]),
+ cmd_loop(Port, Line)
+ end.
+
+%% Convert lonely CR to NL, and CRLF to NL
+%%
+cr_to_nl([$\r,$\n|T]) ->
+ [$\n|cr_to_nl(T)];
+cr_to_nl([$\r|T]) ->
+ [$\n|cr_to_nl(T)];
+cr_to_nl([C|T]) ->
+ [C|cr_to_nl(T)];
+cr_to_nl([]) ->
+ [].
diff --git a/lib/jinterface/test/nc_SUITE.erl b/lib/jinterface/test/nc_SUITE.erl
new file mode 100644
index 0000000000..82dd3c2535
--- /dev/null
+++ b/lib/jinterface/test/nc_SUITE.erl
@@ -0,0 +1,736 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(nc_SUITE).
+
+
+-include("test_server.hrl").
+-include("test_server_line.hrl").
+
+
+-export([all/1,
+ init_per_suite/1,
+ end_per_suite/1,
+ init_per_testcase/2,
+ end_per_testcase/2]).
+
+-export([pid_roundtrip/1,
+ port_roundtrip/1,
+ ref_roundtrip/1,
+ new_float/1,
+ old_stuff/1,
+ binary_roundtrip/1,
+ decompress_roundtrip/1,
+ compress_roundtrip/1,
+ integer_roundtrip/1,
+ fun_roundtrip/1,
+ lists_roundtrip/1,
+ lists_roundtrip_2/1,
+ lists_iterator/1,
+ unicode/1,
+ unicode_list_to_string/1,
+ unicode_string_to_list/1,
+ connect/1]).
+
+
+%% Top of cases
+
+all(doc) -> [];
+all(suite) -> [pid_roundtrip,
+ port_roundtrip,
+ ref_roundtrip,
+ new_float,
+ old_stuff,
+ binary_roundtrip,
+ decompress_roundtrip,
+ compress_roundtrip,
+ integer_roundtrip,
+ fun_roundtrip,
+ lists_roundtrip,
+ lists_roundtrip_2,
+ lists_iterator,
+ unicode,
+ unicode_list_to_string,
+ unicode_string_to_list,
+ connect].
+
+
+
+
+init_per_suite(Config) when is_list(Config) ->
+ jitu:init_all(Config).
+
+end_per_suite(Config) ->
+ jitu:finish_all(Config).
+
+
+
+%% Add/remove watchdog before/after each test case.
+%%
+init_per_testcase(Case, Config) ->
+ T = case atom_to_list(Case) of
+ "unicode"++_ -> 240;
+ _ -> 20
+ end,
+ WatchDog = test_server:timetrap(test_server:seconds(T)),
+ [{watchdog, WatchDog}| Config].
+
+end_per_testcase(_Case, Config) ->
+ WatchDog = ?config(watchdog, Config),
+ test_server:timetrap_cancel(WatchDog).
+
+
+%%
+%% Test cases
+%%
+
+pid_roundtrip(doc) -> [];
+pid_roundtrip(suite) -> [];
+pid_roundtrip(Config) when is_list(Config)->
+ ThisNode = {node(), erlang:system_info(creation)},
+ RemNode = {gurka@sallad, 2},
+ do_echo([self(),
+ mk_pid(ThisNode, 4711, 4711),
+ mk_pid(ThisNode, 32767, 8191),
+ mk_pid(RemNode, 4711, 4711),
+ mk_pid(RemNode, 32767, 8191)],
+ Config).
+
+fun_roundtrip(doc) -> [];
+fun_roundtrip(suite) -> [];
+fun_roundtrip(Config) when is_list(Config)->
+ do_echo([fun(A, B) -> A + B end,
+ fun(A) -> lists:reverse(A) end,
+ fun() -> ok end,
+ fun fun_roundtrip/1],
+ Config).
+
+port_roundtrip(doc) -> [];
+port_roundtrip(suite) -> [];
+port_roundtrip(Config) when is_list(Config)->
+ ThisNode = {node(), erlang:system_info(creation)},
+ RemNode = {gurka@sallad, 2},
+ do_echo([hd(erlang:ports()),
+ mk_port(ThisNode, 4711),
+ mk_port(ThisNode, 268435455),
+ mk_port(RemNode, 4711),
+ mk_port(RemNode, 268435455)],
+ Config).
+
+ref_roundtrip(doc) -> [];
+ref_roundtrip(suite) -> [];
+ref_roundtrip(Config) when is_list(Config)->
+ ThisNode = {node(), erlang:system_info(creation)},
+ RemNode = {gurka@sallad, 2},
+ do_echo([make_ref(),
+ mk_ref(ThisNode, [4711]),
+ mk_ref(ThisNode, [4711, 4711, 4711]),
+ mk_ref(ThisNode, [262143, 4294967295, 4294967295]),
+ mk_ref(RemNode, [4711]),
+ mk_ref(RemNode, [4711, 4711, 4711]),
+ mk_ref(RemNode, [262143, 4294967295, 4294967295])],
+ Config).
+
+new_float(doc) -> [];
+new_float(suite) -> [];
+new_float(Config) when is_list(Config)->
+ Two16 = float(1 bsl 16),
+ X = math:sqrt(2),
+ Floats = lists:reverse(seq(1/X, 63, fun(Y) -> Y / Two16 end),
+ [0.0|seq(X, 63, fun(Y) -> Y * Two16 end)]),
+ io:format("~w", [Floats]),
+ do_echo(Floats, Config).
+
+old_stuff(doc) -> [];
+old_stuff(suite) -> [];
+old_stuff(Config) when is_list(Config)->
+ Terms = [0.0,math:sqrt(2)],
+ OutTrans =
+ fun (D) ->
+ {self(),term_to_binary(D, [{minor_version,0}]),binary}
+ end,
+ InTrans =
+ fun (Echoer, D, {Echoer,D,binary}) ->
+ ok
+ end,
+ do_echo(Terms, Config, OutTrans, InTrans).
+
+binary_roundtrip(doc) -> [];
+binary_roundtrip(suite) -> [];
+binary_roundtrip(Config) when is_list(Config) ->
+ do_echo([<<17>>,
+ <<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17>>,
+ <<3:2>>,
+ <<3,7:3>>,
+ <<>>],
+ Config).
+
+decompress_roundtrip(doc) -> [];
+decompress_roundtrip(suite) -> [];
+decompress_roundtrip(Config) when is_list(Config) ->
+ Terms =
+ [0.0,
+ math:sqrt(2),
+ <<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,31:5>>,
+ make_ref()],
+ OutTrans =
+ fun (D) ->
+ {self(),term_to_binary(D, [compressed]),binary}
+ end,
+ InTrans =
+ fun (Echoer, D, {Echoer,D,binary}) ->
+ ok
+ end,
+ do_echo(Terms, Config, OutTrans, InTrans).
+
+compress_roundtrip(doc) -> [];
+compress_roundtrip(suite) -> [];
+compress_roundtrip(Config) when is_list(Config) ->
+ Terms =
+ [0.0,
+ math:sqrt(2),
+ <<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,31:5>>,
+ make_ref()],
+ OutTrans =
+ fun (D) ->
+ {self(),D,compress}
+ end,
+ InTrans =
+ fun (Echoer, D, {Echoer,B,compress}) ->
+ D = binary_to_term(B)
+ end,
+ do_echo(Terms, Config, OutTrans, InTrans).
+
+
+
+integer_roundtrip(doc) -> [];
+integer_roundtrip(suite) -> [];
+integer_roundtrip(Config) when is_list(Config) ->
+ Xs = [1 bsl X || X <- [26,27,28,29,30,31,32,33,
+ 62,63,64,65,
+ 126,127,128,129]],
+ Terms = [0,1,-1,-2]
+ ++lists:flatmap(fun (X) -> [X-2,X-1,X,-X+1,-X,-X-1] end,
+ Xs),
+ io:format("~w", [Terms]),
+ OutTrans =
+ fun (V) ->
+ {self(),V,bigint}
+ end,
+ InTrans =
+ fun (Echoer, V, {Echoer,{V,W,X,L,U},bigint}) ->
+ Bitlength = bitlength(V),
+ {w,W} = {w,signum(V) * Bitlength},
+ Y = V band 16#FFFFffffFFFFffff,
+ {y,Y} = {y,X band 16#FFFFffffFFFFffff},
+ {l,L} = {l,if V =:= X, Bitlength < 64 -> 1;
+ true -> 0 end},
+ {u,U} = {u,if V =:= Y, V >= 0, Bitlength =< 64 -> 1;
+ true -> 0 end}
+ end,
+ do_echo(Terms, Config, OutTrans, InTrans).
+
+signum(V) when is_integer(V), V > 0 -> 1;
+signum(V) when is_integer(V), V < 0 -> -1;
+signum(0) -> 0.
+
+bitlength(0) ->
+ 0;
+bitlength(-1) ->
+ 0;
+bitlength(V) when is_integer(V) ->
+ 1 + bitlength(V bsr 1).
+
+
+
+lists_roundtrip(doc) -> [];
+lists_roundtrip(suite) -> [];
+lists_roundtrip(Config) when is_list(Config) ->
+ Ls = [lists:seq(1,10),
+ lists:seq(11,17)++last_tail,
+ [{default}],
+ [car|cdr],
+ [[]],
+ []],
+ do_echo(Ls, Config).
+
+
+
+lists_roundtrip_2(doc) -> [];
+lists_roundtrip_2(suite) -> [];
+lists_roundtrip_2(Config) when is_list(Config) ->
+ Ls = [{[a,b],tail},
+ {[c,d,e],tail},
+ {[],tail},
+ {[f],tail},
+ {[g,h|i],tail},
+ {[j,k,l|m],tail},
+ {[n|o],tail},
+ {[z,1,2,3,4],tail3},
+ {[z,5,6,7],tail3},
+ {[z,8,9],tail3},
+ {[z,10],tail3},
+ {[],tail3},
+ {[z,11,12,13,14|15],tail3},
+ {[z,16,17,18|19],tail3},
+ {[z,20,21|22],tail3},
+ {[z,23|24],tail3},
+ {[z|25],tail3},
+ {"abc123",sub3atom},
+ {"abc",sub3atom}
+ ],
+ Trans =
+ fun ([_|T], tail) ->
+ T;
+ (L, tail) when is_list(L) ->
+ null;
+ ([_,_,_|T], tail3) ->
+ T;
+ (L, tail3) when is_list(L) ->
+ null;
+ ([_,_,_|L], sub3atom) ->
+ list_to_atom(L)
+ end,
+ OutTrans =
+ fun ({L,Twist}) ->
+ {self(),L,Twist}
+ end,
+ InTrans =
+ fun (Echoer, {L,Twist}, {Echoer,X,Twist}) ->
+ Y = Trans(L, Twist),
+ io:format("## ~w ~w ~w ~w~n", [L,Twist,X,Y]),
+ X = Y
+ end,
+ do_echo(Ls, Config, OutTrans, InTrans).
+
+
+
+
+lists_iterator(doc) -> [];
+lists_iterator(suite) -> [];
+lists_iterator(Config) when is_list(Config) ->
+ Ls = [["able ","was ","I ","ere ","I ","saw ","elba"]],
+ do_echo(Ls, Config,
+ fun (L) -> {self(),L,strcat} end,
+ fun (Echoer, L, {Echoer,X,strcat}) ->
+ io:format("## ~p ~p~n", [L,X]),
+ X = lists:flatten(L)
+ end).
+
+
+
+unicode(doc) -> [];
+unicode(suite) -> [];
+unicode(Config) when is_list(Config) ->
+ S1 = "plain ascii",
+ S2 = "iso-latin ��� �",
+ S3 = "Codepoints... ��� \x{1000}",
+ S4 = [0,1,31,32,63,64,127,128,255],
+ S5 = [0,1,127,128,255,256,16#d7ff,
+ 16#e000,16#fffd,16#10000,16#10ffff],
+ Ss = [S1,S2,S3,S4,S5],
+ do_echo(unicode_cp_gen([{S,valid} || S <- Ss] ++ cp_gen(71)), Config,
+ fun ({L,invalid}) -> {self(),L,utf8};
+ ({L,Tag}) -> {self(),L,Tag};
+ ({L}) -> {self(),L}
+ end,
+ fun (Echoer, {L,invalid}=Out, {Echoer,X,utf8}=In) ->
+ case L of
+ X -> ok;
+ _ ->
+ ?t:fail({mismatch,Out,In})
+ end;
+ (Echoer, {L,Tag}=Out, {Echoer,X,Tag}=In) ->
+ case unicode:characters_to_binary(L, utf8) of
+ X -> ok;
+ _ ->
+ ?t:fail({mismatch,Out,In})
+ end;
+ (Echoer, {L}=Out, {Echoer,X}=In) ->
+ case L of
+ X -> ok;
+ _ ->
+ ?t:fail({mismatch,Out,In})
+ end
+ end, ["unicode"]).
+
+%% Lazy wrapper to lazy list
+unicode_cp_gen([{S,valid}|Ss]) ->
+ [{S,utf8},{S}|unicode_cp_gen(Ss)];
+unicode_cp_gen([{S,invalid}=St|Ss]) ->
+ [St,{S}|unicode_cp_gen(Ss)];
+unicode_cp_gen([]) ->
+ [];
+unicode_cp_gen(Cont) when is_function(Cont, 0) ->
+ fun () ->
+ unicode_cp_gen(Cont())
+ end.
+
+
+
+unicode_list_to_string(doc) -> [];
+unicode_list_to_string(suite) -> [];
+unicode_list_to_string(Config) when is_list(Config) ->
+ do_echo(cp_gen(73), Config,
+ fun ({L,_}) -> {self(),L,to_string_neg_int_list} end,
+ fun (Echoer, {L,invalid}=Out, {Echoer,X,_}=In) ->
+ case L of
+ X -> ok;
+ _ ->
+ ?t:fail({mismatch,Out,In})
+ end;
+ (Echoer, {L,valid}=Out, {Echoer,X,_}=In) ->
+ B = unicode:characters_to_binary(L, unicode, {utf16,big}),
+ case [-D || <<D:16/big>> <= B] of
+ X -> ok;
+ _ ->
+ ?t:fail({mismatch,Out,In})
+ end
+ end).
+
+
+
+unicode_string_to_list(doc) -> [];
+unicode_string_to_list(suite) -> [];
+unicode_string_to_list(Config) when is_list(Config) ->
+ do_echo(cp_gen(79), Config,
+ fun ({L,_}) -> {self(),L,to_neg_int_list} end,
+ fun (Echoer, {L,invalid}=Out, {Echoer,X,_}=In) ->
+ case L of
+ X -> ok;
+ _ ->
+ ?t:fail({mismatch,Out,In})
+ end;
+ (Echoer, {L,valid}=Out, {Echoer,X,_}=In) ->
+ case [-C || C <- L] of
+ X -> ok;
+ _ ->
+ ?t:fail({mismatch,Out,In})
+ end
+ end, ["unicode"]).
+
+
+%% Lazy list
+cp_gen(N) ->
+ cp_gen(N, -1, 16#110000).
+
+cp_gen(N, Start, End) ->
+ cp_gen(N, Start, End, cp_validity(Start), [], 0, [], 0).
+
+cp_gen(N, U, End, PrevValidity, Acc, Len, Ss, Ls) when Len >= N ->
+ cp_gen(N, U, End, PrevValidity, [], 0, [{Acc,PrevValidity}|Ss], Ls+1);
+cp_gen(N, U, End, PrevValidity, Acc, Len, Ss, Ls) when Ls >= N ->
+ Ss ++ fun () ->
+ cp_gen(N, U, End, PrevValidity, Acc, Len, [], 0)
+ end;
+cp_gen(_, U, End, _, Acc, _, Ss, _) when U > End ->
+ [{Acc,valid}|Ss];
+cp_gen(N, U, End, PrevValidity, Acc, Len, Ss, Ls) ->
+ Validity = cp_validity(U),
+ NextU = U+1,
+ {NextAcc,NextLen} = case Validity of
+ valid -> {[U|Acc],Len+1};
+ invalid -> {Acc,Len}
+ end,
+ {NextSs,NextLs} = case Validity of
+ PrevValidity -> {Ss,Ls};
+ valid -> {[{[U-1],PrevValidity}|Ss],Ls+1};
+ invalid -> {[{[U],Validity}|Ss],Ls+1}
+ end,
+ cp_gen(N, NextU, End, Validity, NextAcc, NextLen, NextSs, NextLs).
+
+cp_validity(UnicodeCP) ->
+ try <<UnicodeCP/big-utf32>> of
+ _ -> valid
+ catch
+ error:_ -> invalid
+ end.
+
+
+
+connect(doc) -> [];
+connect(suite) -> [];
+connect(Config) when is_list(Config) ->
+ WD = filename:dirname(code:which(?MODULE)),
+ {ok,Other} = ?t:start_node(make_name(), slave, [{args,"-pa "++WD}]),
+ Action =
+ fun (Pid) ->
+ JName = node(Pid),
+ Hidden = [JName],
+ Pid ! {self(),Other},
+ receive
+ {Pid,Other,true} ->
+ ok;
+ Unexpected1 ->
+ ?t:fail({result,Unexpected1})
+ end,
+ Hidden = erlang:nodes(hidden),
+ Hidden = rpc:call(Other, erlang, nodes, [hidden]),
+ true =
+ rpc:call(Other, erlang, disconnect_node, [JName]),
+ [] =
+ rpc:call(Other, erlang, nodes, [hidden]),
+ Hidden = erlang:nodes(hidden),
+ %% Again
+ receive after 2000 -> ok end,
+ %% We have no way of knowing when the Java node
+ %% detects the nodedown.
+ Pid ! {self(),Other},
+ receive
+ {Pid,Other,true} ->
+ ok;
+ Unexpected2->
+ ?t:fail({result,Unexpected2})
+ end,
+ Hidden = rpc:call(Other, erlang, nodes, [hidden])
+ end,
+ run_server(connection_server, Config, Action, []).
+
+
+
+seq(_, 0, _) ->
+ [];
+seq(X, N, Fun) ->
+ [X|seq(Fun(X), N-1, Fun)].
+
+do_echo(DataList, Config) ->
+ do_echo(DataList, Config,
+ fun (D) -> % OutTrans
+ {self(),D}
+ end,
+ fun (Echoer, D, {Echoer,D}) -> % InTrans
+ ok
+ end, []).
+
+do_echo(DataList, Config, OutTrans, InTrans) ->
+ do_echo(DataList, Config, OutTrans, InTrans, []).
+
+do_echo(DataList, Config, OutTrans, InTrans, ExtraArgs)
+ when is_list(DataList), is_list(Config) ->
+ run_server(echo_server, Config,
+ fun (Echoer) ->
+ echo_loop(DataList, Echoer, OutTrans, InTrans, [])
+ end,
+ ExtraArgs).
+
+echo_loop([D|Ds], Echoer, OutTrans, InTrans, TermAcc) ->
+ OutMsg = OutTrans(D),
+ Echoer ! OutMsg,
+ io:format("echo_server ~p: ~p ! ~P~n", [self(),Echoer,OutMsg,10]),
+ receive
+ Reply ->
+ io:format("echo_server ~p: receive ~P~n",
+ [self(),Reply,10]),
+ InTrans(Echoer, D, Reply)
+ end,
+ Term = case OutMsg of
+ {_, T, _} -> T;
+ {_, T} -> T
+ end,
+ echo_loop(Ds, Echoer, OutTrans, InTrans, [Term | TermAcc]);
+echo_loop([], Echoer, _, _, TermAcc) ->
+ check_terms(Echoer, TermAcc);
+%% Lazy list
+echo_loop(Cont, Echoer, OutTrans, InTrans, TermAcc)
+ when is_function(Cont, 0) ->
+ check_terms(Echoer, TermAcc),
+ OutMsg = Echoer ! {self(),undefined,hash_clear},
+ io:format("echo_server ~p: ~p ! ~P~n", [self(),Echoer,OutMsg,10]),
+ receive
+ {Echoer,hash_cleared,hash_clear}=Reply ->
+ io:format("echo_server ~p: receive ~P~n",
+ [self(),Reply,10]),
+ ok;
+ Other ->
+ io:format("echo_server_terms unexpected ~p: receive ~P~n",
+ [self(),Other,10]),
+ ?t:fail({unexpected, Other})
+ end,
+ echo_loop(Cont(), Echoer, OutTrans, InTrans, []).
+
+check_terms(Echoer, [Term | Rest]) ->
+ OutMsg = {self(),Term,hash_lookup},
+ Echoer ! OutMsg,
+ io:format("check_terms ~p: ~p ! ~P~n", [self(),Echoer,OutMsg,10]),
+ receive
+ {Echoer,true,hash_lookup} = ReplyMsg ->
+ io:format("check_terms ~p: receive ~P~n",
+ [self(),ReplyMsg,10]),
+ check_terms(Echoer, Rest);
+ Other ->
+ io:format("check_terms unexpected ~p: receive ~P~n",
+ [self(),Other,10]),
+ ?t:fail({unexpected, Other})
+ end;
+check_terms(_, []) ->
+ ok.
+
+run_server(Server, Config, Action, ExtraArgs) ->
+ Name = make_name(),
+ true = register(Name, self()),
+ JName = make_name(),
+ spawn_link(fun () ->
+ ok = jitu:java(?config(java, Config),
+ ?config(data_dir, Config),
+ atom_to_list(Server),
+ [JName,
+ erlang:get_cookie(),
+ node(),
+ Name]++ExtraArgs
+ ),
+ %,"-DOtpConnection.trace=3"),
+ Name ! {done, JName}
+ end),
+ receive
+ {Server, JName, Pid} ->
+ ?t:format("~w: ~p (~p)~n",
+ [Server, Pid, node(Pid)]),
+ ?t:format("nodes(hidden): ~p~n",
+ [nodes(hidden)]),
+ Action(Pid),
+ Pid ! bye,
+ receive
+ {done, JName} ->
+ ok
+ end;
+ Other ->
+ ?t:fail({unexpected,Other})
+ end.
+
+%%
+%% Utils...
+%%
+
+make_name() ->
+ {A, B, C} = now(),
+ list_to_atom(atom_to_list(?MODULE)
+ ++ "-" ++ integer_to_list(A)
+ ++ "-" ++ integer_to_list(B)
+ ++ "-" ++ integer_to_list(C)).
+
+
+
+-define(VERSION_MAGIC, 131).
+
+-define(ATOM_EXT, 100).
+-define(REFERENCE_EXT, 101).
+-define(PORT_EXT, 102).
+-define(PID_EXT, 103).
+-define(NEW_REFERENCE_EXT, 114).
+
+uint32_be(Uint) when is_integer(Uint), 0 =< Uint, Uint < 1 bsl 32 ->
+ [(Uint bsr 24) band 16#ff,
+ (Uint bsr 16) band 16#ff,
+ (Uint bsr 8) band 16#ff,
+ Uint band 16#ff];
+uint32_be(Uint) ->
+ exit({badarg, uint32_be, [Uint]}).
+
+
+uint16_be(Uint) when is_integer(Uint), 0 =< Uint, Uint < 1 bsl 16 ->
+ [(Uint bsr 8) band 16#ff,
+ Uint band 16#ff];
+uint16_be(Uint) ->
+ exit({badarg, uint16_be, [Uint]}).
+
+uint8(Uint) when is_integer(Uint), 0 =< Uint, Uint < 1 bsl 8 ->
+ Uint band 16#ff;
+uint8(Uint) ->
+ exit({badarg, uint8, [Uint]}).
+
+
+
+mk_pid({NodeName, Creation}, Number, Serial) when is_atom(NodeName) ->
+ mk_pid({atom_to_list(NodeName), Creation}, Number, Serial);
+mk_pid({NodeName, Creation}, Number, Serial) ->
+ case catch binary_to_term(list_to_binary([?VERSION_MAGIC,
+ ?PID_EXT,
+ ?ATOM_EXT,
+ uint16_be(length(NodeName)),
+ NodeName,
+ uint32_be(Number),
+ uint32_be(Serial),
+ uint8(Creation)])) of
+ Pid when is_pid(Pid) ->
+ Pid;
+ {'EXIT', {badarg, _}} ->
+ exit({badarg, mk_pid, [{NodeName, Creation}, Number, Serial]});
+ Other ->
+ exit({unexpected_binary_to_term_result, Other})
+ end.
+
+mk_port({NodeName, Creation}, Number) when is_atom(NodeName) ->
+ mk_port({atom_to_list(NodeName), Creation}, Number);
+mk_port({NodeName, Creation}, Number) ->
+ case catch binary_to_term(list_to_binary([?VERSION_MAGIC,
+ ?PORT_EXT,
+ ?ATOM_EXT,
+ uint16_be(length(NodeName)),
+ NodeName,
+ uint32_be(Number),
+ uint8(Creation)])) of
+ Port when is_port(Port) ->
+ Port;
+ {'EXIT', {badarg, _}} ->
+ exit({badarg, mk_port, [{NodeName, Creation}, Number]});
+ Other ->
+ exit({unexpected_binary_to_term_result, Other})
+ end.
+
+mk_ref({NodeName, Creation}, Numbers) when is_atom(NodeName),
+ is_integer(Creation),
+ is_list(Numbers) ->
+ mk_ref({atom_to_list(NodeName), Creation}, Numbers);
+mk_ref({NodeName, Creation}, [Number]) when is_list(NodeName),
+ is_integer(Creation),
+ is_integer(Number) ->
+ case catch binary_to_term(list_to_binary([?VERSION_MAGIC,
+ ?REFERENCE_EXT,
+ ?ATOM_EXT,
+ uint16_be(length(NodeName)),
+ NodeName,
+ uint32_be(Number),
+ uint8(Creation)])) of
+ Ref when is_reference(Ref) ->
+ Ref;
+ {'EXIT', {badarg, _}} ->
+ exit({badarg, mk_ref, [{NodeName, Creation}, [Number]]});
+ Other ->
+ exit({unexpected_binary_to_term_result, Other})
+ end;
+mk_ref({NodeName, Creation}, Numbers) when is_list(NodeName),
+ is_integer(Creation),
+ is_list(Numbers) ->
+ case catch binary_to_term(list_to_binary([?VERSION_MAGIC,
+ ?NEW_REFERENCE_EXT,
+ uint16_be(length(Numbers)),
+ ?ATOM_EXT,
+ uint16_be(length(NodeName)),
+ NodeName,
+ uint8(Creation),
+ lists:map(fun (N) ->
+ uint32_be(N)
+ end,
+ Numbers)])) of
+ Ref when is_reference(Ref) ->
+ Ref;
+ {'EXIT', {badarg, _}} ->
+ exit({badarg, mk_ref, [{NodeName, Creation}, Numbers]});
+ Other ->
+ exit({unexpected_binary_to_term_result, Other})
+ end.
diff --git a/lib/jinterface/test/nc_SUITE_data/Makefile.src b/lib/jinterface/test/nc_SUITE_data/Makefile.src
new file mode 100644
index 0000000000..3d131250be
--- /dev/null
+++ b/lib/jinterface/test/nc_SUITE_data/Makefile.src
@@ -0,0 +1,53 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2004-2010. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+
+# Makefile.src for java_client_erl_server test
+# Note: This file *must* work for both Unix and Windows
+#
+# We use both `rm' (Unix) and `del' (Windows) for removing files, but
+# with a `-' in front so that the error in not finding `rm' (`del') on
+# Windows (Unix) is ignored.
+#
+# VxWorks? XXX
+#
+
+.SUFFIXES:
+.SUFFIXES: .java
+
+
+JAVAC = @JAVAC@
+ERLC = erlc
+
+JINTERFACE_CLASSPATH = @jinterface_classpath@
+
+CLASSPATH = .@PS@$(JINTERFACE_CLASSPATH)@PS@
+
+JAVA_FILES = echo_server.java connection_server.java
+CLASS_FILES = $(JAVA_FILES:.java=.class)
+
+all: $(CLASS_FILES)
+
+clean:
+ -rm -f $(CLASS_FILES)
+ -del /F /Q $(CLASS_FILES)
+
+$(CLASS_FILES) : $(JAVA_FILES)
+ $(JAVAC) -classpath $(CLASSPATH) $(JAVA_FILES)
+
+#
diff --git a/lib/jinterface/test/nc_SUITE_data/connection_server.java b/lib/jinterface/test/nc_SUITE_data/connection_server.java
new file mode 100644
index 0000000000..19ed1c7d5c
--- /dev/null
+++ b/lib/jinterface/test/nc_SUITE_data/connection_server.java
@@ -0,0 +1,96 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2004-2010. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+import com.ericsson.otp.erlang.*;
+
+public class connection_server {
+ static java.lang.String Name = "connection_server";
+
+ public static void main(String[] argv) {
+ try {
+ System.out.println("connection_server booting...");
+
+ for (int j = 0; j < argv.length; j++)
+ System.out.println("argv[" + j + "] = \"" + argv[j] + "\"");
+
+ if (argv.length != 4) {
+ System.out.println("Wrong number of arguments!");
+ System.exit(1);
+ }
+
+ // Start node and mbox
+ OtpNode node = new OtpNode(argv[0], argv[1]);
+ OtpMbox mbox = node.createMbox();
+ if (! mbox.registerName(Name)) {
+ System.out.println("Could not register name " + Name);
+ System.exit(3);
+ }
+
+ // Announce our presence
+ OtpErlangObject[] amsg = new OtpErlangObject[3];
+ amsg[0] = new OtpErlangAtom(Name);
+ amsg[1] = new OtpErlangAtom(argv[0]);
+ amsg[2] = mbox.self();
+ OtpErlangTuple atuple = new OtpErlangTuple(amsg);
+ mbox.send(argv[3], argv[2], atuple);
+
+ // Do connects ...
+ while (true) {
+ OtpErlangObject o = mbox.receive();
+ if (o == null)
+ continue;
+ if (o instanceof OtpErlangTuple) {
+ OtpErlangTuple msg = (OtpErlangTuple) o;
+ OtpErlangPid from = (OtpErlangPid)(msg.elementAt(0));
+ OtpErlangAtom conn_node = (OtpErlangAtom) msg.elementAt(1);
+
+ System.out.println("Got request to connect to: "
+ + conn_node);
+ OtpErlangObject[] rmsg = new OtpErlangObject[3];
+ rmsg[0] = mbox.self();
+ rmsg[1] = conn_node;
+ if (node.ping(conn_node.atomValue(), 1000)) {
+ System.out.println("Successfully connected to "
+ + conn_node.toString());
+ rmsg[2] = new OtpErlangAtom("true");
+ }
+ else {
+ System.out.println("Failed to connect to "
+ + conn_node.toString());
+ rmsg[2] = new OtpErlangAtom("false");
+ }
+
+ OtpErlangTuple rtuple = new OtpErlangTuple(rmsg);
+
+ mbox.send(from, rtuple);
+ }
+ else { // probably 'bye'
+ System.out.println("connection_server halting...");
+ System.exit(0);
+ }
+ }
+ }
+ catch (Exception e) {
+ System.out.println("" + e);
+ System.exit(2);
+ }
+
+ }
+
+}
diff --git a/lib/jinterface/test/nc_SUITE_data/echo_server.java b/lib/jinterface/test/nc_SUITE_data/echo_server.java
new file mode 100644
index 0000000000..0550e4beb1
--- /dev/null
+++ b/lib/jinterface/test/nc_SUITE_data/echo_server.java
@@ -0,0 +1,261 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2004-2010. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+import java.io.UnsupportedEncodingException;
+import java.util.HashSet;
+
+import com.ericsson.otp.erlang.OtpErlangAtom;
+import com.ericsson.otp.erlang.OtpErlangBinary;
+import com.ericsson.otp.erlang.OtpErlangBoolean;
+import com.ericsson.otp.erlang.OtpErlangException;
+import com.ericsson.otp.erlang.OtpErlangInt;
+import com.ericsson.otp.erlang.OtpErlangList;
+import com.ericsson.otp.erlang.OtpErlangLong;
+import com.ericsson.otp.erlang.OtpErlangObject;
+import com.ericsson.otp.erlang.OtpErlangPid;
+import com.ericsson.otp.erlang.OtpErlangString;
+import com.ericsson.otp.erlang.OtpErlangTuple;
+import com.ericsson.otp.erlang.OtpExternal;
+import com.ericsson.otp.erlang.OtpInputStream;
+import com.ericsson.otp.erlang.OtpMbox;
+import com.ericsson.otp.erlang.OtpNode;
+import com.ericsson.otp.erlang.OtpOutputStream;
+
+public class echo_server {
+ private static boolean debug = false;
+
+ public static void main(final String[] argv) {
+ try {
+ System.out.println("echo_server booting...");
+
+ for (int j = 0; j < argv.length; j++) {
+ System.out.println("argv[" + j + "] = \"" + argv[j] + "\"");
+ }
+
+ if (argv.length != 4 && argv.length != 5) {
+ System.out.println("Wrong number of arguments!");
+ System.exit(1);
+ }
+
+ // Start node and mbox
+ final OtpNode node = new OtpNode(argv[0], argv[1]);
+ if (argv.length == 5 && argv[4].equals("unicode")) {
+ System.out.println("Setting unicode string mode.");
+ node.setFlags(OtpInputStream.DECODE_INT_LISTS_AS_STRINGS);
+ }
+ final OtpMbox mbox = node.createMbox();
+
+ // Announce our presence
+ final OtpErlangObject[] amsg = new OtpErlangObject[3];
+ amsg[0] = new OtpErlangAtom("echo_server");
+ amsg[1] = new OtpErlangAtom(argv[0]);
+ amsg[2] = mbox.self();
+ final OtpErlangTuple atuple = new OtpErlangTuple(amsg);
+ mbox.send(argv[3], argv[2], atuple);
+
+ // Do echoing...
+ while (true) {
+ final OtpErlangObject o = mbox.receive();
+ if (o == null) {
+ continue;
+ }
+ if (o instanceof OtpErlangTuple) {
+ final OtpErlangTuple msg = (OtpErlangTuple) o;
+ final int arity = msg.arity();
+ if (arity < 2) {
+ System.out
+ .println("Arity < 2; echo_server aborting...");
+ System.exit(2);
+ } else if (arity == 2) {
+ final OtpErlangPid from = (OtpErlangPid) msg
+ .elementAt(0);
+ if (debug) System.out.println("Echoing: "
+ + msg.elementAt(1));
+
+ final OtpErlangObject[] rmsg = new OtpErlangObject[2];
+ rmsg[0] = mbox.self();
+ rmsg[1] = msg.elementAt(1);
+ final OtpErlangTuple rtuple = new OtpErlangTuple(rmsg);
+
+ mbox.send(from, rtuple);
+ continue;
+ } else if (arity == 3) {
+ echoTwisted(mbox, msg);
+ continue;
+ } else {
+ System.out
+ .println("Arity > 3; echo_server aborting...");
+ System.exit(2);
+ }
+ } else if (o instanceof OtpErlangAtom) {
+ OtpErlangAtom a = (OtpErlangAtom) o;
+ if (a.atomValue().equals("debug")) {
+ debug = true;
+ } else if (a.atomValue().equals("bye")) {
+ System.out.println("echo_server halting...");
+ System.exit(0);
+ }
+ } else { // probably 'bye'
+ }
+ System.out.println("Unexpected: " + o +
+ " echo_server aborting...");
+ System.exit(2);
+ }
+ } catch (final Exception e) {
+ System.out.println("" + e);
+ System.exit(2);
+ }
+ }
+
+ private static void echoTwisted(final OtpMbox mbox,
+ final OtpErlangTuple msg)
+ throws OtpErlangException {
+ final OtpErlangPid from = (OtpErlangPid) msg.elementAt(0);
+
+ final OtpErlangObject[] rmsg = new OtpErlangObject[3];
+ if (debug) System.out.println("Echo in: " + msg);
+ rmsg[0] = mbox.self();
+ rmsg[1] = twist(msg.elementAt(1), rmsg[2] = msg.elementAt(2));
+ final OtpErlangTuple rtuple = new OtpErlangTuple(rmsg);
+ if (debug) System.out.println("Echo out: " + rtuple);
+
+ mbox.send(from, rtuple);
+ }
+
+ private static HashSet<OtpErlangObject> hash_set =
+ new HashSet<OtpErlangObject>();
+
+ private static OtpErlangObject twist(final OtpErlangObject i,
+ final OtpErlangObject t) throws OtpErlangException {
+ hash_set.add(i);
+ if (t instanceof OtpErlangAtom) {
+ final String atomValue = ((OtpErlangAtom) t).atomValue();
+ if (atomValue.equals("binary") && i instanceof OtpErlangBinary) {
+ final OtpErlangBinary b = (OtpErlangBinary) i;
+ final OtpInputStream bis = new OtpInputStream(b.binaryValue(),
+ 0);
+ final OtpErlangObject o = bis.read_any();
+ return o;
+ } else if (atomValue.equals("compress")) {
+ final OtpOutputStream oos = new OtpOutputStream();
+ oos.write1(OtpExternal.versionTag);
+ oos.write_compressed(i);
+ final OtpErlangBinary o =
+ new OtpErlangBinary(oos.toByteArray());
+ return o;
+ } else if (atomValue.equals("bigint")
+ && i instanceof OtpErlangLong) {
+ final OtpErlangLong l = (OtpErlangLong) i;
+ final int w = l.signum() * l.bitLength();
+ final OtpErlangLong x = new OtpErlangLong(l.longValue());
+ final java.math.BigInteger b = l.bigIntegerValue();
+ System.out.println("long: " + l + ": " + w + ": " + b.signum()
+ * b.bitLength() + ": " + x + ": " + l.isLong() + ": "
+ + l.isULong());
+ return new OtpErlangTuple(new OtpErlangObject[] { l,
+ new OtpErlangInt(w), x,
+ new OtpErlangInt(l.isLong() ? 1 : 0),
+ new OtpErlangInt(l.isULong() ? 1 : 0) });
+ } else if (atomValue.equals("tail")
+ && i instanceof OtpErlangList) {
+ final OtpErlangObject o = ((OtpErlangList) i).getTail();
+ if (o == null) {
+ return new OtpErlangAtom("null");
+ }
+ return o;
+ } else if (atomValue.equals("tail3")
+ && i instanceof OtpErlangList) {
+ final OtpErlangObject o = ((OtpErlangList) i).getNthTail(3);
+ if (o == null) {
+ return new OtpErlangAtom("null");
+ }
+ return o;
+ } else if (atomValue.equals("strcat")
+ && i instanceof OtpErlangList) {
+ final java.lang.StringBuffer b = new java.lang.StringBuffer();
+ final OtpErlangList l = (OtpErlangList) i;
+ for (final OtpErlangObject j : l) {
+ final OtpErlangString k = (OtpErlangString) j;
+ b.append(k.stringValue());
+ }
+ final OtpErlangObject o = new OtpErlangString(b.toString());
+ return o;
+ } else if (atomValue.equals("sub3atom")
+ && i instanceof OtpErlangString) {
+ final OtpErlangString s = (OtpErlangString) i;
+ final OtpErlangAtom o = new OtpErlangAtom(s.stringValue()
+ .substring(3));
+ return o;
+ } else if (atomValue.equals("utf8")) {
+ if (i instanceof OtpErlangString) {
+ final OtpErlangString s = (OtpErlangString) i;
+ byte[] bytes;
+ try {
+ bytes = s.stringValue().getBytes("UTF-8");
+ } catch (final UnsupportedEncodingException e) {
+ bytes = new byte[] { 'e', 'r', 'r', 'o', 'r' };
+ }
+ final OtpErlangBinary b = new OtpErlangBinary(bytes);
+ return b;
+ }
+ } else if(atomValue.equals("to_string_neg_int_list")) {
+ OtpErlangString oes = null;
+ if (i instanceof OtpErlangString) {
+ oes = (OtpErlangString) i;
+ } else if (i instanceof OtpErlangList) {
+ OtpErlangList oel = (OtpErlangList) i;
+ try {
+ oes = new OtpErlangString(oel);
+ } catch (final Exception e) {
+ }
+ }
+ if (oes != null) {
+ String s = oes.stringValue();
+ int n = s.length();
+ OtpErlangObject l[] = new OtpErlangObject[n];
+ for (int j = 0; j < n; j++) {
+ int c = s.charAt(j);
+ l[j] = new OtpErlangInt(-c);
+ }
+ return new OtpErlangList(l);
+ }
+ } else if(atomValue.equals("to_neg_int_list")) {
+ if (i instanceof OtpErlangString) {
+ OtpErlangString oes = (OtpErlangString) i;
+ OtpErlangList oel = new OtpErlangList(oes.stringValue());
+ int n = oel.arity();
+ OtpErlangObject l[] = new OtpErlangObject[n];
+ for (int j = 0; j < n; j++) {
+ OtpErlangLong c = (OtpErlangLong) oel.elementAt(j);
+ l[j] = new OtpErlangInt(-c.intValue());
+ }
+ return new OtpErlangList(l);
+ }
+ } else if (atomValue.equals("hash_lookup")) {
+ final boolean exists = hash_set.contains(i);
+ final OtpErlangBoolean b = new OtpErlangBoolean(exists);
+ return b;
+ } else if (atomValue.equals("hash_clear")) {
+ hash_set.clear();
+ return new OtpErlangAtom("hash_cleared");
+ }
+ }
+ return i;
+ }
+}
diff --git a/lib/jinterface/vsn.mk b/lib/jinterface/vsn.mk
index 6b5719d7c5..ed085b5d4d 100644
--- a/lib/jinterface/vsn.mk
+++ b/lib/jinterface/vsn.mk
@@ -1,19 +1 @@
-##
-## %CopyrightBegin%
-##
-## Copyright Ericsson AB 2000-2010. All Rights Reserved.
-##
-## The contents of this file are subject to the Erlang Public License,
-## Version 1.1, (the "License"); you may not use this file except in
-## compliance with the License. You should have received a copy of the
-## Erlang Public License along with this software. If not, it can be
-## retrieved online at http://www.erlang.org/.
-##
-## Software distributed under the License is distributed on an "AS IS"
-## basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-## the License for the specific language governing rights and limitations
-## under the License.
-##
-## %CopyrightEnd%
-
-JINTERFACE_VSN = 1.5.3
+JINTERFACE_VSN = 1.5.3.1
diff --git a/lib/kernel/doc/src/erl_ddll.xml b/lib/kernel/doc/src/erl_ddll.xml
index 4e65bf46f8..9a62b45d63 100644
--- a/lib/kernel/doc/src/erl_ddll.xml
+++ b/lib/kernel/doc/src/erl_ddll.xml
@@ -177,7 +177,7 @@
<name>demonitor(MonitorRef) -> ok</name>
<fsummary>Remove a monitor for a driver</fsummary>
<type>
- <v>MonitorRef = ref()</v>
+ <v>MonitorRef = reference()</v>
</type>
<desc>
<p>Removes a driver monitor in much the same way as
@@ -185,7 +185,7 @@
monitors. See <seealso marker="#monitor/2">monitor/2</seealso>, <seealso marker="#try_load/3">try_load/3</seealso> and <seealso marker="#try_unload/2">try_unload/2</seealso> for details
about how to create driver monitors.</p>
<p>The function throws a <c>badarg</c> exception if the
- parameter is not a ref(). </p>
+ parameter is not a reference(). </p>
</desc>
</func>
<func>
@@ -400,7 +400,7 @@
<v>Item = {Name, When}</v>
<v>Name = atom() | string()</v>
<v>When = loaded | unloaded | unloaded_only</v>
- <v>MonitorRef = ref()</v>
+ <v>MonitorRef = reference()</v>
</type>
<desc>
<p>This function creates a driver monitor and works in many
@@ -449,7 +449,7 @@
eventually lead to one of the following messages
being sent:</p>
<taglist>
- <tag><em>{'UP', ref(), driver, Name, loaded}</em></tag>
+ <tag><em>{'UP', reference(), driver, Name, loaded}</em></tag>
<item>
<p>This message is sent, either immediately if the
driver is already loaded and no reloading is
@@ -459,7 +459,7 @@
expected to know if reloading is demanded prior
to creating a monitor for loading.</p>
</item>
- <tag><em>{'UP', ref(), driver, Name, permanent}</em></tag>
+ <tag><em>{'UP', reference(), driver, Name, permanent}</em></tag>
<item>
<p>This message will be sent if reloading was
expected, but the (old) driver made itself
@@ -467,7 +467,7 @@
sent if the driver was permanent or statically
linked in when trying to create the monitor.</p>
</item>
- <tag><em>{'DOWN', ref(), driver, Name, load_cancelled}</em></tag>
+ <tag><em>{'DOWN', reference(), driver, Name, load_cancelled}</em></tag>
<item>
<p>This message will arrive if reloading was
underway, but the <seealso marker="#users">user</seealso> having requested
@@ -476,7 +476,7 @@
(or <c>unload/1</c>/<c>unload_driver/1</c>)
again before it was reloaded.</p>
</item>
- <tag><em>{'DOWN', ref(), driver, Name, {load_failure, Failure}}</em></tag>
+ <tag><em>{'DOWN', reference(), driver, Name, {load_failure, Failure}}</em></tag>
<item>
<p>This message will arrive if reloading was
underway but the loading for some reason
@@ -500,7 +500,7 @@
<p>A driver monitor for unload will eventually result
in one of the following messages being sent:</p>
<taglist>
- <tag><em>{'DOWN', ref(), driver, Name, unloaded}</em></tag>
+ <tag><em>{'DOWN', reference(), driver, Name, unloaded}</em></tag>
<item>
<p>The driver instance monitored is now
unloaded. As the unload might have been due to a
@@ -508,7 +508,7 @@
again have been loaded when this message
arrives.</p>
</item>
- <tag><em>{'UP', ref(), driver, Name, unload_cancelled}</em></tag>
+ <tag><em>{'UP', reference(), driver, Name, unload_cancelled}</em></tag>
<item>
<p>This message will be sent if unloading was
expected, but while the driver was waiting for
@@ -525,7 +525,7 @@
similar to an <c>unloaded</c> monitor, but does
never result in this message.</p>
</item>
- <tag><em>{'UP', ref(), driver, Name, permanent}</em></tag>
+ <tag><em>{'UP', reference(), driver, Name, permanent}</em></tag>
<item>
<p>This message will be sent if unloading was
expected, but the driver made itself
@@ -539,7 +539,7 @@
<item>
<p>A monitor created as <c>unloaded_only</c> behaves
exactly as one created as <c>unloaded</c> with the
- exception that the <c>{'UP', ref(), driver, Name, unload_cancelled}</c> message will never be
+ exception that the <c>{'UP', reference(), driver, Name, unload_cancelled}</c> message will never be
sent, but the monitor instead persists until the
driver <em>really</em> gets unloaded.</p>
</item>
@@ -626,7 +626,7 @@
<v>ReloadOption = pending_driver | pending</v>
<v>Status = loaded | already_loaded | PendingStatus </v>
<v>PendingStatus = pending_driver | pending_process</v>
- <v>Ref = ref()</v>
+ <v>Ref = reference()</v>
<v>ErrorDesc = ErrorAtom | OpaqueError</v>
<v>ErrorAtom = linked_in_driver | inconsistent | permanent | not_loaded_by_this_process | not_loaded | pending_reload | pending_process</v>
</type>
@@ -650,7 +650,7 @@
registered and a corresponding <c>try_unload</c> is
expected sometime in the future.</p>
</item>
- <tag><em>{ok, pending_driver}</em>or <em>{ok, pending_driver, ref()}</em></tag>
+ <tag><em>{ok, pending_driver}</em>or <em>{ok, pending_driver, reference()}</em></tag>
<item>
<p>The load request is registered, but the loading is
delayed due to the fact that an earlier instance of the
@@ -665,7 +665,7 @@
set. In other words, this return value will always need
to be handled!</p>
</item>
- <tag><em>{ok, pending_process}</em>or <em>{ok, pending_process, ref()}</em></tag>
+ <tag><em>{ok, pending_process}</em>or <em>{ok, pending_process, reference()}</em></tag>
<item>
<p>The load request is registered, but the loading is
delayed due to the fact that an earlier instance of the
@@ -683,7 +683,7 @@
about when the driver is <em>actually</em> loaded. This can
be achieved by using the <c>{monitor, PendingOption}</c> option.</p>
<p>When monitoring is requested, and a corresponding <c>{ok, pending_driver}</c> or <c>{ok, pending_process}</c> would be
- returned, the function will instead return a tuple <c>{ok, PendingStatus, ref()}</c> and the process will, at a later
+ returned, the function will instead return a tuple <c>{ok, PendingStatus, reference()}</c> and the process will, at a later
time when the driver actually gets loaded, get a monitor
message. The monitor message one can expect is described in
the <seealso marker="#monitor/2">monitor/2</seealso>
@@ -760,7 +760,7 @@
<p>A <c>MonitorOption</c> tells <c>try_load/3</c> to
trigger a driver monitor under certain
conditions. When the monitor is triggered, the
- function will return a three-tuple <c>{ok, PendingStatus, ref()}</c>, where the <c>ref()</c> is
+ function will return a three-tuple <c>{ok, PendingStatus, reference()}</c>, where the <c>reference()</c> is
the monitor ref for the driver monitor.</p>
<p>Only one <c>MonitorOption</c> can be specified and
it is either the atom <c>pending</c>, which means
@@ -891,7 +891,7 @@
<v>MonitorOption = pending_driver | pending</v>
<v>Status = unloaded | PendingStatus </v>
<v>PendingStatus = pending_driver | pending_process</v>
- <v>Ref = ref()</v>
+ <v>Ref = reference()</v>
<v>ErrorAtom = linked_in_driver | not_loaded | not_loaded_by_this_process | permanent</v>
</type>
<desc>
@@ -943,7 +943,7 @@
ports using it and there are no more <seealso marker="#users">users</seealso> requiring it to be
loaded.</p>
</item>
- <tag><em>{ok, pending_driver}</em>or <em>{ok, pending_driver, ref()}</em></tag>
+ <tag><em>{ok, pending_driver}</em>or <em>{ok, pending_driver, reference()}</em></tag>
<item>
<p>This return value indicates that this call removed the
last <seealso marker="#users">user</seealso> from the
@@ -957,7 +957,7 @@
in that case, however transient. Monitors are as always
useful to detect when the driver is really unloaded.</p>
</item>
- <tag><em>{ok, pending_process}</em>or <em>{ok, pending_process, ref()}</em></tag>
+ <tag><em>{ok, pending_process}</em>or <em>{ok, pending_process, reference()}</em></tag>
<item>
<p>The unload request is registered, but there are still
other <seealso marker="#users">users</seealso> holding
diff --git a/lib/kernel/doc/src/gen_tcp.xml b/lib/kernel/doc/src/gen_tcp.xml
index 032dcc5251..8e7192a496 100644
--- a/lib/kernel/doc/src/gen_tcp.xml
+++ b/lib/kernel/doc/src/gen_tcp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2009</year>
+ <year>1997</year><year>2010</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -284,9 +284,10 @@ socket()
<type>
<v>Socket = socket()</v>
<v>Length = int()</v>
- <v>Packet = [char()] | binary()</v>
+ <v>Packet = [char()] | binary() | HttpPacket</v>
<v>Timeout = int() | infinity</v>
<v>Reason = closed | posix()</v>
+ <v>HttpPacket = see the description of <c>HttpPacket</c> in <seealso marker="erts:erlang#decode_packet/3">erlang:decode_packet/3</seealso></v>
</type>
<desc>
<p>This function receives a packet from a socket in passive
diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml
index 2ae230152c..a22c0a8346 100644
--- a/lib/kernel/doc/src/inet.xml
+++ b/lib/kernel/doc/src/inet.xml
@@ -220,6 +220,69 @@ fe80::204:acff:fe17:bf38
<p>Returns the local hostname. Will never fail.</p>
</desc>
</func>
+
+ <func>
+ <name>getifaddrs() -> {ok,Iflist} | {error,posix}</name>
+ <fsummary>Return a list of interfaces and their addresses</fsummary>
+ <type>
+ <v>Iflist = {Ifname,[Ifopt]}</v>
+ <v>Ifname = string()</v>
+ <v>Ifopt = {flag,[Flag]} | {addr,Addr} | {netmask,Netmask}
+ | {broadaddr,Broadaddr} | {dstaddr,Dstaddr}
+ | {hwaddr,Hwaddr}</v>
+ <v>Flag = up | broadcast | loopback | pointtopoint
+ | running | multicast</v>
+ <v>Addr = Netmask = Broadadddr = Dstaddr = ip_address()</v>
+ <v>Hwaddr = [byte()]</v>
+ </type>
+ </func>
+ <desc>
+ <p>
+ Returns a list of 2-tuples containing interface names and the
+ interface's addresses. <c>Ifname</c> is a Unicode string.
+ <c>Hwaddr</c> is hardware dependent, e.g on Ethernet interfaces
+ it is the 6-byte Ethernet address (MAC address (EUI-48 address)).
+ </p>
+ <p>
+ The <c>{addr,Addr}</c>, <c>{netmask,_}</c> and <c>{broadaddr,_}</c>
+ tuples are repeated in the result list iff the interface has multiple
+ addresses. If you come across an interface that has
+ multiple <c>{flag,_}</c> or <c>{hwaddr,_}</c> tuples you have
+ a really strange interface or possibly a bug in this function.
+ The <c>{flag,_}</c> tuple is mandatory, all other optional.
+ </p>
+ <p>
+ Do not rely too much on the order of <c>Flag</c> atoms or
+ <c>Ifopt</c> tuples. There are some rules, though:
+ <list>
+ <item>
+ Immediately after <c>{addr,_}</c> follows <c>{netmask,_}</c>
+ </item>
+ <item>
+ Immediately thereafter follows <c>{broadaddr,_}</c> if
+ the <c>broadcast</c> flag is <em>not</em> set and the
+ <c>pointtopoint</c>flag <em>is</em> set.
+ </item>
+ <item>
+ Any <c>{netmask,_}</c>, <c>{broadaddr,_}</c> or
+ <c>{dstaddr,_}</c> tuples that follow an <c>{addr,_}</c>
+ tuple concerns that address.
+ </item>
+ </list>
+ </p>
+ <p>
+ The <c>{hwaddr,_}</c> tuple is not returned on Solaris since the
+ hardware address historically belongs to the link layer and only
+ the superuser can read such addresses.
+ </p>
+ <p>
+ On Windows, the data is fetched from quite different OS API
+ functions, so the <c>Netmask</c> and <c>Broadaddr</c>
+ values may be calculated, just as some <c>Flag</c> values.
+ You have been warned. Report flagrant bugs.
+ </p>
+ </desc>
+
<func>
<name>getopts(Socket, Options) -> {ok, OptionValues} | {error, posix()}</name>
<fsummary>Get one or more options for a socket</fsummary>
diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml
index b503716037..edd6ea52b0 100644
--- a/lib/kernel/doc/src/notes.xml
+++ b/lib/kernel/doc/src/notes.xml
@@ -30,6 +30,127 @@
</header>
<p>This document describes the changes made to the Kernel application.</p>
+<section><title>Kernel 2.14.1.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>In embedded mode, on_load handlers that called
+ <c>code:priv_dir/1</c> or other functions in <c>code</c>
+ would hang the system. Since the <c>crypto</c>
+ application now contains an on_loader handler that calls
+ <c>code:priv_dir/1</c>, including the <c>crypto</c>
+ application in the boot file would prevent the system
+ from starting.</p>
+ <p>Also extended the <c>-init_debug</c> option to print
+ information about on_load handlers being run to
+ facilitate debugging.</p>
+ <p>
+ Own Id: OTP-8902 Aux Id: seq11703 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 2.14.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed: inet:setopts(S, [{linger,{true,2}}]) returned
+ {error,einval} for SCTP sockets. The inet_drv had a bug
+ when checking the option size.</p>
+ <p>
+ Own Id: OTP-8726 Aux Id: seq11617 </p>
+ </item>
+ <item>
+ <p>
+ gen_udp:connect/3 was broken for SCTP enabled builds. It
+ did not detect remote end errors as it should.</p>
+ <p>
+ Own Id: OTP-8729</p>
+ </item>
+ <item>
+ <p>reference() has been substituted for ref() in the
+ documentation.</p>
+ <p>
+ Own Id: OTP-8733</p>
+ </item>
+ <item>
+ <p>A bug introduced in kernel-2.13.5.3 has been fixed. If
+ running <c>net_kernel:set_net_ticktime/1</c> twice within
+ the <c>TransitionPerod</c> the second call caused the
+ net_kernel process to crash with a <c>badmatch</c>.</p>
+ <p>
+ Own Id: OTP-8787 Aux Id: seq11657, OTP-8643 </p>
+ </item>
+ <item>
+ <p>
+ inet:getsockopt for SCTP sctp_default_send_param had a
+ bug to not initialize required feilds causing random
+ answers. It is now corrected.</p>
+ <p>
+ Own Id: OTP-8795 Aux Id: seq11655 </p>
+ </item>
+ <item>
+ <p>For a socket in the HTTP packet mode, the return value
+ from <c>gen_tcp:recv/2,3</c> if there is an error in the
+ header will be <c>{ok,{http_error,String}}</c> instead of
+ <c>{error,{http_error,String}}</c> to be consistent with
+ <c>ssl:recv/2,3</c>.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-8831</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Even when configuring erlang with --enable-native-libs,
+ the native code for modules loaded very early (such as
+ lists) would not get loaded. This has been corrected.
+ (Thanks to Paul Guyot.)</p>
+ <p>
+ Own Id: OTP-8750</p>
+ </item>
+ <item>
+ <p>
+ The undocumented function inet:ifget/2 has been improved
+ to return interface hardware address (MAC) on platforms
+ supporting getaddrinfo() (such as BSD unixes). Note it
+ still does not work on all platforms for example not
+ Windows nor Solaris, so the function is still
+ undocumented.</p>
+ <p>
+ Buffer overflow and field init bugs for inet:ifget/2 and
+ inet:getservbyname/2 has also been fixed.</p>
+ <p>
+ Thanks to Michael Santos.</p>
+ <p>
+ Own Id: OTP-8816</p>
+ </item>
+ <item>
+ <p>
+ As a usability improvement the 'inet6' option to
+ functions gen_tcp:listen/2, gen_tcp:connect/3-4,
+ gen_udp:open/2 and gen_sctp:open/1-2 is now implicit if
+ the address argument or the 'ip' option contain an IPv6
+ address (8-tuple).</p>
+ <p>
+ Own Id: OTP-8822</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Kernel 2.14</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/kernel/src/erl_epmd.erl b/lib/kernel/src/erl_epmd.erl
index 4a22637304..91af49f303 100644
--- a/lib/kernel/src/erl_epmd.erl
+++ b/lib/kernel/src/erl_epmd.erl
@@ -210,19 +210,6 @@ open({A,B,C,D,E,F,G,H}=EpmdAddr, Timeout) when ?ip6(A,B,C,D,E,F,G,H) ->
close(Socket) ->
gen_tcp:close(Socket).
-
-do_register_node_v0(NodeName, TcpPort) ->
- case open() of
- {ok, Socket} ->
- Name = cstring(NodeName),
- Len = 1+2+length(Name),
- gen_tcp:send(Socket, [?int16(Len), ?EPMD_ALIVE,
- ?int16(TcpPort), Name]),
- wait_for_reg_reply_v0(Socket, []);
- Error ->
- Error
- end.
-
do_register_node(NodeName, TcpPort) ->
case open() of
{ok, Socket} ->
@@ -240,14 +227,7 @@ do_register_node(NodeName, TcpPort) ->
Name,
?int16(Elen),
Extra]),
- case wait_for_reg_reply(Socket, []) of
- {error, epmd_close} ->
- %% could be old epmd; try old protocol
-% erlang:display('trying old'),
- do_register_node_v0(NodeName, TcpPort);
- Other ->
- Other
- end;
+ wait_for_reg_reply(Socket, []);
Error ->
Error
end.
@@ -305,41 +285,9 @@ wait_for_reg_reply(Socket, SoFar) ->
{error, no_reg_reply_from_epmd}
end.
-wait_for_reg_reply_v0(Socket, SoFar) ->
- receive
- {tcp, Socket, Data0} ->
- case SoFar ++ Data0 of
- [$Y, A, B] ->
- {alive, Socket, ?u16(A, B)};
- Data when length(Data) < 3 ->
- wait_for_reg_reply(Socket, Data);
- Garbage ->
- {error, {garbage_from_epmd, Garbage}}
- end;
- {tcp_closed, Socket} ->
- {error, duplicate_name} % A guess -- the most likely reason.
- after 10000 ->
- gen_tcp:close(Socket),
- {error, no_reg_reply_from_epmd}
- end.
%%
%% Lookup a node "Name" at Host
%%
-get_port_v0(Node, EpmdAddress) ->
- case open(EpmdAddress) of
- {ok, Socket} ->
- Name = cstring(Node),
- Len = 1+length(Name),
- gen_tcp:send(Socket, [?int16(Len),?EPMD_PORT_PLEASE, Name]),
- wait_for_port_reply_v0(Socket, []);
- _Error ->
- ?port_please_failure(),
- noport
- end.
-
-%%% Not used anymore
-%%% get_port(Node, EpmdAddress) ->
-%%% get_port(Node, EpmdAddress, infinity).
get_port(Node, EpmdAddress, Timeout) ->
case open(EpmdAddress, Timeout) of
@@ -347,40 +295,12 @@ get_port(Node, EpmdAddress, Timeout) ->
Name = to_string(Node),
Len = 1+length(Name),
gen_tcp:send(Socket, [?int16(Len),?EPMD_PORT_PLEASE2_REQ, Name]),
- Reply = wait_for_port_reply(Socket, []),
- case Reply of
- closed ->
- get_port_v0(Node, EpmdAddress);
- Other ->
- Other
- end;
+ wait_for_port_reply(Socket, []);
_Error ->
?port_please_failure2(_Error),
noport
end.
-wait_for_port_reply_v0(Socket, SoFar) ->
- receive
- {tcp, Socket, Data0} ->
-% io:format("got ~p~n", [Data0]),
- case SoFar ++ Data0 of
- [A, B] ->
- wait_for_close(Socket, {port, ?u16(A, B), 0});
-% wait_for_close(Socket, {port, ?u16(A, B)});
- Data when length(Data) < 2 ->
- wait_for_port_reply_v0(Socket, Data);
- Garbage ->
- ?port_please_failure(),
- {error, {garbage_from_epmd, Garbage}}
- end;
- {tcp_closed, Socket} ->
- ?port_please_failure(),
- noport
- after 10000 ->
- ?port_please_failure(),
- gen_tcp:close(Socket),
- noport
- end.
wait_for_port_reply(Socket, SoFar) ->
receive
@@ -487,8 +407,6 @@ wait_for_close(Socket, Reply) ->
%%
%% Creates a (flat) null terminated string from atom or list.
%%
-cstring(S) when is_atom(S) -> cstring(atom_to_list(S));
-cstring(S) when is_list(S) -> S ++ [0].
to_string(S) when is_atom(S) -> atom_to_list(S);
to_string(S) when is_list(S) -> S.
diff --git a/lib/kernel/src/erl_epmd.hrl b/lib/kernel/src/erl_epmd.hrl
index 47ab6195d8..5a50fda508 100644
--- a/lib/kernel/src/erl_epmd.hrl
+++ b/lib/kernel/src/erl_epmd.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -17,16 +17,13 @@
%% %CopyrightEnd%
%%
--define(EPMD_ALIVE, $a).
--define(EPMD_PORT_PLEASE, $p).
--define(EPMD_NAMES, $n).
--define(EPMD_DUMP, $d).
--define(EPMD_KILL, $k).
--define(EPMD_STOP, $s).
-
--define(EPMD_ALIVE_OK, $Y).
-
-define(EPMD_ALIVE2_REQ, $x).
-define(EPMD_PORT_PLEASE2_REQ, $z).
-define(EPMD_ALIVE2_RESP, $y).
-define(EPMD_PORT2_RESP, $w).
+-define(EPMD_NAMES, $n).
+
+%% Commands used only by interactive client
+-define(EPMD_DUMP, $d).
+-define(EPMD_KILL, $k).
+-define(EPMD_STOP, $s).
diff --git a/lib/kernel/src/gen_sctp.erl b/lib/kernel/src/gen_sctp.erl
index 5a31e3976f..cccfa75005 100644
--- a/lib/kernel/src/gen_sctp.erl
+++ b/lib/kernel/src/gen_sctp.erl
@@ -39,7 +39,7 @@ open() ->
open([]).
open(Opts) when is_list(Opts) ->
- Mod = mod(Opts),
+ Mod = mod(Opts, undefined),
case Mod:open(Opts) of
{error,badarg} ->
erlang:error(badarg, [Opts]);
@@ -166,18 +166,14 @@ send(S, #sctp_assoc_change{assoc_id=AssocId}, Stream, Data)
when is_port(S), is_integer(Stream) ->
case inet_db:lookup_socket(S) of
{ok,Mod} ->
- Mod:sendmsg(S, #sctp_sndrcvinfo{
- stream = Stream,
- assoc_id = AssocId}, Data);
+ Mod:send(S, AssocId, Stream, Data);
Error -> Error
end;
send(S, AssocId, Stream, Data)
when is_port(S), is_integer(AssocId), is_integer(Stream) ->
case inet_db:lookup_socket(S) of
{ok,Mod} ->
- Mod:sendmsg(S, #sctp_sndrcvinfo{
- stream = Stream,
- assoc_id = AssocId}, Data);
+ Mod:send(S, AssocId, Stream, Data);
Error -> Error
end;
send(S, AssocChange, Stream, Data) ->
@@ -238,17 +234,27 @@ controlling_process(S, Pid) ->
%% Utilites
%%
-%% Get the SCTP moudule
-mod() -> inet_db:sctp_module().
+%% Get the SCTP module, but IPv6 address overrides default IPv4
+mod(Address) ->
+ case inet_db:sctp_module() of
+ inet_sctp when tuple_size(Address) =:= 8 ->
+ inet6_sctp;
+ Mod ->
+ Mod
+ end.
%% Get the SCTP module, but option sctp_module|inet|inet6 overrides
-mod([{sctp_module,Mod}|_]) ->
+mod([{sctp_module,Mod}|_], _Address) ->
Mod;
-mod([inet|_]) ->
+mod([inet|_], _Address) ->
inet_sctp;
-mod([inet6|_]) ->
+mod([inet6|_], _Address) ->
inet6_sctp;
-mod([_|Opts]) ->
- mod(Opts);
-mod([]) ->
- mod().
+mod([{ip, Address}|Opts], _) ->
+ mod(Opts, Address);
+mod([{ifaddr, Address}|Opts], _) ->
+ mod(Opts, Address);
+mod([_|Opts], Address) ->
+ mod(Opts, Address);
+mod([], Address) ->
+ mod(Address).
diff --git a/lib/kernel/src/gen_tcp.erl b/lib/kernel/src/gen_tcp.erl
index 7401b06a64..16a87d71b6 100644
--- a/lib/kernel/src/gen_tcp.erl
+++ b/lib/kernel/src/gen_tcp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -46,7 +46,7 @@ connect(Address, Port, Opts, Time) ->
end.
connect1(Address,Port,Opts,Timer) ->
- Mod = mod(Opts),
+ Mod = mod(Opts, Address),
case Mod:getaddrs(Address,Timer) of
{ok,IPs} ->
case Mod:getserv(Port) of
@@ -73,7 +73,7 @@ try_connect([], _Port, _Opts, _Timer, _Mod, Err) ->
%% Listen on a tcp port
%%
listen(Port, Opts) ->
- Mod = mod(Opts),
+ Mod = mod(Opts, undefined),
case Mod:getserv(Port) of
{ok,TP} ->
Mod:listen(TP, Opts);
@@ -173,20 +173,30 @@ controlling_process(S, NewOwner) ->
%% Create a port/socket from a file descriptor
%%
fdopen(Fd, Opts) ->
- Mod = mod(Opts),
+ Mod = mod(Opts, undefined),
Mod:fdopen(Fd, Opts).
-%% Get the tcp_module
-mod() -> inet_db:tcp_module().
+%% Get the tcp_module, but IPv6 address overrides default IPv4
+mod(Address) ->
+ case inet_db:tcp_module() of
+ inet_tcp when tuple_size(Address) =:= 8 ->
+ inet6_tcp;
+ Mod ->
+ Mod
+ end.
%% Get the tcp_module, but option tcp_module|inet|inet6 overrides
-mod([{tcp_module,Mod}|_]) ->
+mod([{tcp_module,Mod}|_], _Address) ->
Mod;
-mod([inet|_]) ->
+mod([inet|_], _Address) ->
inet_tcp;
-mod([inet6|_]) ->
+mod([inet6|_], _Address) ->
inet6_tcp;
-mod([_|Opts]) ->
- mod(Opts);
-mod([]) ->
- mod().
+mod([{ip, Address}|Opts], _) ->
+ mod(Opts, Address);
+mod([{ifaddr, Address}|Opts], _) ->
+ mod(Opts, Address);
+mod([_|Opts], Address) ->
+ mod(Opts, Address);
+mod([], Address) ->
+ mod(Address).
diff --git a/lib/kernel/src/gen_udp.erl b/lib/kernel/src/gen_udp.erl
index 6bded4bda6..99020c7b6c 100644
--- a/lib/kernel/src/gen_udp.erl
+++ b/lib/kernel/src/gen_udp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -29,7 +29,7 @@ open(Port) ->
open(Port, []).
open(Port, Opts) ->
- Mod = mod(Opts),
+ Mod = mod(Opts, undefined),
{ok,UP} = Mod:getserv(Port),
Mod:open(UP, Opts).
@@ -97,21 +97,31 @@ controlling_process(S, NewOwner) ->
%% Create a port/socket from a file descriptor
%%
fdopen(Fd, Opts) ->
- Mod = mod(),
+ Mod = mod(Opts, undefined),
Mod:fdopen(Fd, Opts).
-%% Get the udp_module
-mod() -> inet_db:udp_module().
+%% Get the udp_module, but IPv6 address overrides default IPv4
+mod(Address) ->
+ case inet_db:udp_module() of
+ inet_udp when tuple_size(Address) =:= 8 ->
+ inet6_udp;
+ Mod ->
+ Mod
+ end.
%% Get the udp_module, but option udp_module|inet|inet6 overrides
-mod([{udp_module,Mod}|_]) ->
+mod([{udp_module,Mod}|_], _Address) ->
Mod;
-mod([inet|_]) ->
+mod([inet|_], _Address) ->
inet_udp;
-mod([inet6|_]) ->
+mod([inet6|_], _Address) ->
inet6_udp;
-mod([_|Opts]) ->
- mod(Opts);
-mod([]) ->
- mod().
+mod([{ip, Address}|Opts], _) ->
+ mod(Opts, Address);
+mod([{ifaddr, Address}|Opts], _) ->
+ mod(Opts, Address);
+mod([_|Opts], Address) ->
+ mod(Opts, Address);
+mod([], Address) ->
+ mod(Address).
diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl
index 93d75321ba..327e0f93f1 100644
--- a/lib/kernel/src/inet.erl
+++ b/lib/kernel/src/inet.erl
@@ -25,6 +25,7 @@
%% socket
-export([peername/1, sockname/1, port/1, send/2,
setopts/2, getopts/2,
+ getifaddrs/0, getifaddrs/1,
getif/1, getif/0, getiflist/0, getiflist/1,
ifget/3, ifget/2, ifset/3, ifset/2,
getstat/1, getstat/2,
@@ -265,6 +266,17 @@ setopts(Socket, Opts) ->
getopts(Socket, Opts) ->
prim_inet:getopts(Socket, Opts).
+-spec getifaddrs(Socket :: socket()) ->
+ {'ok', [string()]} | {'error', posix()}.
+
+getifaddrs(Socket) ->
+ prim_inet:getifaddrs(Socket).
+
+-spec getifaddrs() -> {'ok', [string()]} | {'error', posix()}.
+
+getifaddrs() ->
+ withsocket(fun(S) -> prim_inet:getifaddrs(S) end).
+
-spec getiflist(Socket :: socket()) ->
{'ok', [string()]} | {'error', posix()}.
diff --git a/lib/kernel/src/inet6_sctp.erl b/lib/kernel/src/inet6_sctp.erl
index 5c49c4fec3..5bf3fca647 100644
--- a/lib/kernel/src/inet6_sctp.erl
+++ b/lib/kernel/src/inet6_sctp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -32,7 +32,7 @@
-define(FAMILY, inet6).
-export([getserv/1,getaddr/1,getaddr/2,translate_ip/1]).
--export([open/1,close/1,listen/2,connect/5,sendmsg/3,recv/2]).
+-export([open/1,close/1,listen/2,connect/5,sendmsg/3,send/4,recv/2]).
@@ -71,5 +71,24 @@ connect(S, Addr, Port, Opts, Timer) ->
sendmsg(S, SRI, Data) ->
prim_inet:sendmsg(S, SRI, Data).
+send(S, AssocId, Stream, Data) ->
+ case prim_inet:getopts(
+ S,
+ [{sctp_default_send_param,#sctp_sndrcvinfo{assoc_id=AssocId}}]) of
+ {ok,
+ [{sctp_default_send_param,
+ #sctp_sndrcvinfo{
+ flags=Flags, context=Context, ppid=PPID, timetolive=TTL}}]} ->
+ prim_inet:sendmsg(
+ S,
+ #sctp_sndrcvinfo{
+ flags=Flags, context=Context, ppid=PPID, timetolive=TTL,
+ assoc_id=AssocId, stream=Stream},
+ Data);
+ _ ->
+ prim_inet:sendmsg(
+ S, #sctp_sndrcvinfo{assoc_id=AssocId, stream=Stream}, Data)
+ end.
+
recv(S, Timeout) ->
prim_inet:recvfrom(S, 0, Timeout).
diff --git a/lib/kernel/src/inet_config.erl b/lib/kernel/src/inet_config.erl
index 311e6bc9f9..2458876326 100644
--- a/lib/kernel/src/inet_config.erl
+++ b/lib/kernel/src/inet_config.erl
@@ -23,6 +23,8 @@
-import(lists, [foreach/2, member/2, reverse/1]).
+%% Avoid warning for local function error/2 clashing with autoimported BIF.
+-compile({no_auto_import,[error/2]}).
-export([init/0]).
-export([do_load_resolv/2]).
diff --git a/lib/kernel/src/inet_int.hrl b/lib/kernel/src/inet_int.hrl
index cf357b7fba..6f1688c6a2 100644
--- a/lib/kernel/src/inet_int.hrl
+++ b/lib/kernel/src/inet_int.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -82,6 +82,7 @@
-define(INET_REQ_IFGET, 22).
-define(INET_REQ_IFSET, 23).
-define(INET_REQ_SUBSCRIBE, 24).
+-define(INET_REQ_GETIFADDRS, 25).
%% TCP requests
-define(TCP_REQ_ACCEPT, 40).
-define(TCP_REQ_LISTEN, 41).
diff --git a/lib/kernel/src/inet_parse.erl b/lib/kernel/src/inet_parse.erl
index 3bd5fa0958..65edddcb46 100644
--- a/lib/kernel/src/inet_parse.erl
+++ b/lib/kernel/src/inet_parse.erl
@@ -20,6 +20,8 @@
%% Parser for all kinds of ineternet configuration files
+%% Avoid warning for local function error/2 clashing with autoimported BIF.
+-compile({no_auto_import,[error/2]}).
-export([hosts/1, hosts/2]).
-export([hosts_vxworks/1]).
-export([protocols/1, protocols/2]).
diff --git a/lib/kernel/src/inet_sctp.erl b/lib/kernel/src/inet_sctp.erl
index 795bf83807..de74b573bd 100644
--- a/lib/kernel/src/inet_sctp.erl
+++ b/lib/kernel/src/inet_sctp.erl
@@ -31,7 +31,7 @@
-define(FAMILY, inet).
-export([getserv/1,getaddr/1,getaddr/2,translate_ip/1]).
--export([open/1,close/1,listen/2,connect/5,sendmsg/3,recv/2]).
+-export([open/1,close/1,listen/2,connect/5,sendmsg/3,send/4,recv/2]).
@@ -141,5 +141,24 @@ connect_get_assoc(S, Addr, Port, Active, Timer) ->
sendmsg(S, SRI, Data) ->
prim_inet:sendmsg(S, SRI, Data).
+send(S, AssocId, Stream, Data) ->
+ case prim_inet:getopts(
+ S,
+ [{sctp_default_send_param,#sctp_sndrcvinfo{assoc_id=AssocId}}]) of
+ {ok,
+ [{sctp_default_send_param,
+ #sctp_sndrcvinfo{
+ flags=Flags, context=Context, ppid=PPID, timetolive=TTL}}]} ->
+ prim_inet:sendmsg(
+ S,
+ #sctp_sndrcvinfo{
+ flags=Flags, context=Context, ppid=PPID, timetolive=TTL,
+ assoc_id=AssocId, stream=Stream},
+ Data);
+ _ ->
+ prim_inet:sendmsg(
+ S, #sctp_sndrcvinfo{assoc_id=AssocId, stream=Stream}, Data)
+ end.
+
recv(S, Timeout) ->
prim_inet:recvfrom(S, 0, Timeout).
diff --git a/lib/kernel/src/kernel.erl b/lib/kernel/src/kernel.erl
index 92ee7b441a..1e07620a3e 100644
--- a/lib/kernel/src/kernel.erl
+++ b/lib/kernel/src/kernel.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -143,6 +143,13 @@ init(safe) ->
Boot = start_boot_server(),
DiskLog = start_disk_log(),
Pg2 = start_pg2(),
+
+ %% Run the on_load handlers for all modules that have been
+ %% loaded so far. Running them at this point means that
+ %% on_load handlers can safely call kernel processes
+ %% (and in particular call code:priv_dir/1 or code:lib_dir/1).
+ init:run_on_load_handlers(),
+
{ok, {SupFlags, Boot ++ DiskLog ++ Pg2}}.
get_code_args() ->
diff --git a/lib/kernel/src/net_kernel.erl b/lib/kernel/src/net_kernel.erl
index 0e5cc8c2c6..f5e2820bbe 100644
--- a/lib/kernel/src/net_kernel.erl
+++ b/lib/kernel/src/net_kernel.erl
@@ -500,8 +500,8 @@ handle_call({new_ticktime,T,TP}, From, #state{tick = #tick{ticker = Tckr,
time = T,
how = How}}}, From);
-handle_call({new_ticktime,From,_},
- _,
+handle_call({new_ticktime,_T,_TP},
+ From,
#state{tick = #tick_change{time = T}} = State) ->
async_reply({reply, {ongoing_change_to, T}, State}, From);
diff --git a/lib/kernel/test/code_SUITE_data/on_load_app-1.0/src/on_load_embedded.erl b/lib/kernel/test/code_SUITE_data/on_load_app-1.0/src/on_load_embedded.erl
index a39332f81d..b7fdd4d9ae 100644
--- a/lib/kernel/test/code_SUITE_data/on_load_app-1.0/src/on_load_embedded.erl
+++ b/lib/kernel/test/code_SUITE_data/on_load_app-1.0/src/on_load_embedded.erl
@@ -3,6 +3,15 @@
-on_load(run_me/0).
run_me() ->
+ %% An onload handler typically calls code:priv_dir/1
+ %% or code:lib_dir/1, so make sure that it works.
+ LibDir = code:lib_dir(on_load_app),
+ PrivDir = code:priv_dir(on_load_app),
+ LibDir = filename:dirname(PrivDir),
+ ModPath = code:which(?MODULE),
+ LibDir = filename:dirname(filename:dirname(ModPath)),
+
+ %% Start a process to remember that the on_load was called.
spawn(fun() ->
register(everything_is_fine, self()),
receive Any ->
diff --git a/lib/kernel/test/erl_distribution_SUITE.erl b/lib/kernel/test/erl_distribution_SUITE.erl
index d15f6aa0d5..21a96f804a 100644
--- a/lib/kernel/test/erl_distribution_SUITE.erl
+++ b/lib/kernel/test/erl_distribution_SUITE.erl
@@ -273,6 +273,7 @@ tick_change(Config) when is_list(Config) ->
?line PaDir = filename:dirname(code:which(?MODULE)),
?line [BN, CN] = get_nodenames(2, tick_change),
?line DefaultTT = net_kernel:get_net_ticktime(),
+ ?line unchanged = net_kernel:set_net_ticktime(DefaultTT, 60),
?line case DefaultTT of
I when is_integer(I) -> ?line ok;
_ -> ?line ?t:fail(DefaultTT)
@@ -377,6 +378,7 @@ run_tick_change_test(B, C, PrevTT, TT, PaDir) ->
end,
?line change_initiated = net_kernel:set_net_ticktime(TT,20),
+ ?line {ongoing_change_to,_} = net_kernel:set_net_ticktime(TT,20),
?line sleep(3),
?line change_initiated = rpc:call(B,net_kernel,set_net_ticktime,[TT,15]),
?line sleep(7),
diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl
index fad8c7398b..9aa94a0868 100644
--- a/lib/kernel/test/gen_sctp_SUITE.erl
+++ b/lib/kernel/test/gen_sctp_SUITE.erl
@@ -23,12 +23,16 @@
%%-compile(export_all).
--export([all/1,init_per_testcase/2,fin_per_testcase/2,
- basic/1,api_open_close/1,api_listen/1,api_connect_init/1,
- xfer_min/1,xfer_active/1]).
+-export([all/1,init_per_testcase/2,fin_per_testcase/2]).
+-export(
+ [basic/1,
+ api_open_close/1,api_listen/1,api_connect_init/1,api_opts/1,
+ xfer_min/1,xfer_active/1,def_sndrcvinfo/1,implicit_inet6/1]).
all(suite) ->
- [basic,api_open_close,api_listen,api_connect_init,xfer_min,xfer_active].
+ [basic,
+ api_open_close,api_listen,api_connect_init,api_opts,
+ xfer_min,xfer_active,def_sndrcvinfo,implicit_inet6].
init_per_testcase(_Func, Config) ->
Dog = test_server:timetrap(test_server:seconds(15)),
@@ -39,6 +43,10 @@ fin_per_testcase(_Func, Config) ->
+-define(LOGVAR(Var), begin io:format(??Var" = ~p~n", [Var]) end).
+
+
+
basic(doc) ->
"Hello world";
basic(suite) ->
@@ -214,12 +222,17 @@ xfer_active(Config) when is_list(Config) ->
end,
?line ok = gen_sctp:close(Sb),
?line receive
- {sctp,Sa,Loopback,Pb,
- {[],
- #sctp_assoc_change{state=comm_lost,
- assoc_id=SaAssocId}}} -> ok
- after 17 -> ok %% On Solaris this does not arrive
- end,
+ {sctp,Sa,Loopback,Pb,
+ {[],
+ #sctp_assoc_change{state=comm_lost,
+ assoc_id=SaAssocId}}} -> ok
+ after Timeout ->
+ ?line test_server:fail({unexpected,flush()})
+ end,
+ ?line receive
+ {sctp_error,Sa,enotconn} -> ok % Solaris
+ after 17 -> ok %% Only happens on Solaris
+ end,
?line ok = gen_sctp:close(Sa),
%%
?line receive
@@ -228,6 +241,148 @@ xfer_active(Config) when is_list(Config) ->
end,
ok.
+def_sndrcvinfo(doc) ->
+ "Test that #sctp_sndrcvinfo{} parameters set on a socket "
+ "are used by gen_sctp:send/4";
+def_sndrcvinfo(suite) ->
+ [];
+def_sndrcvinfo(Config) when is_list(Config) ->
+ ?line Loopback = {127,0,0,1},
+ ?line Data = <<"What goes up, must come down.">>,
+ %%
+ ?line S1 =
+ ok(gen_sctp:open(
+ 0, [{sctp_default_send_param,#sctp_sndrcvinfo{ppid=17}}])),
+ ?LOGVAR(S1),
+ ?line P1 =
+ ok(inet:port(S1)),
+ ?LOGVAR(P1),
+ ?line #sctp_sndrcvinfo{ppid=17, context=0, timetolive=0, assoc_id=0} =
+ getopt(S1, sctp_default_send_param),
+ ?line ok =
+ gen_sctp:listen(S1, true),
+ %%
+ ?line S2 =
+ ok(gen_sctp:open()),
+ ?LOGVAR(S2),
+ ?line P2 =
+ ok(inet:port(S2)),
+ ?LOGVAR(P2),
+ ?line #sctp_sndrcvinfo{ppid=0, context=0, timetolive=0, assoc_id=0} =
+ getopt(S2, sctp_default_send_param),
+ %%
+ ?line #sctp_assoc_change{
+ state=comm_up,
+ error=0,
+ assoc_id=S2AssocId} = S2AssocChange =
+ ok(gen_sctp:connect(S2, Loopback, P1, [])),
+ ?LOGVAR(S2AssocChange),
+ ?line case ok(gen_sctp:recv(S1)) of
+ {Loopback, P2,[],
+ #sctp_assoc_change{
+ state=comm_up,
+ error=0,
+ assoc_id=S1AssocId}} ->
+ ?LOGVAR(S1AssocId)
+ end,
+ ?line #sctp_sndrcvinfo{
+ ppid=17, context=0, timetolive=0, assoc_id=S1AssocId} =
+ getopt(
+ S1, sctp_default_send_param, #sctp_sndrcvinfo{assoc_id=S1AssocId}),
+ ?line #sctp_sndrcvinfo{
+ ppid=0, context=0, timetolive=0, assoc_id=S2AssocId} =
+ getopt(
+ S2, sctp_default_send_param, #sctp_sndrcvinfo{assoc_id=S2AssocId}),
+ %%
+ ?line ok =
+ gen_sctp:send(S1, S1AssocId, 1, <<"1: ",Data/binary>>),
+ ?line case ok(gen_sctp:recv(S2)) of
+ {Loopback,P1,
+ [#sctp_sndrcvinfo{
+ stream=1, ppid=17, context=0, assoc_id=S2AssocId}],
+ <<"1: ",Data/binary>>} -> ok
+ end,
+ %%
+ ?line ok =
+ setopt(
+ S1, sctp_default_send_param, #sctp_sndrcvinfo{ppid=18}),
+ ?line ok =
+ setopt(
+ S1, sctp_default_send_param,
+ #sctp_sndrcvinfo{ppid=19, assoc_id=S1AssocId}),
+ ?line #sctp_sndrcvinfo{
+ ppid=18, context=0, timetolive=0, assoc_id=0} =
+ getopt(S1, sctp_default_send_param),
+ ?line #sctp_sndrcvinfo{
+ ppid=19, context=0, timetolive=0, assoc_id=S1AssocId} =
+ getopt(
+ S1, sctp_default_send_param, #sctp_sndrcvinfo{assoc_id=S1AssocId}),
+ %%
+ ?line ok =
+ gen_sctp:send(S1, S1AssocId, 0, <<"2: ",Data/binary>>),
+ ?line case ok(gen_sctp:recv(S2)) of
+ {Loopback,P1,
+ [#sctp_sndrcvinfo{
+ stream=0, ppid=19, context=0, assoc_id=S2AssocId}],
+ <<"2: ",Data/binary>>} -> ok
+ end,
+ ?line ok =
+ gen_sctp:send(S2, S2AssocChange, 1, <<"3: ",Data/binary>>),
+ ?line case ok(gen_sctp:recv(S1)) of
+ {Loopback,P2,
+ [#sctp_sndrcvinfo{
+ stream=1, ppid=0, context=0, assoc_id=S1AssocId}],
+ <<"3: ",Data/binary>>} -> ok;
+ {Loopback,P2,[],
+ #sctp_paddr_change{
+ addr={Loopback,_}, state=addr_available,
+ error=0, assoc_id=S1AssocId}} ->
+ ?line case ok(gen_sctp:recv(S1)) of
+ {Loopback,P2,
+ [#sctp_sndrcvinfo{
+ stream=1, ppid=0, context=0,
+ assoc_id=S1AssocId}],
+ <<"3: ",Data/binary>>} -> ok
+ end
+ end,
+ ?line ok =
+ gen_sctp:send(
+ S2,
+ #sctp_sndrcvinfo{stream=0, ppid=20, assoc_id=S2AssocId},
+ <<"4: ",Data/binary>>),
+ ?line case ok(gen_sctp:recv(S1)) of
+ {Loopback,P2,
+ [#sctp_sndrcvinfo{
+ stream=0, ppid=20, context=0, assoc_id=S1AssocId}],
+ <<"4: ",Data/binary>>} -> ok
+ end,
+ %%
+ ?line ok =
+ gen_sctp:close(S1),
+ ?line ok =
+ gen_sctp:close(S2),
+ ?line receive
+ Msg ->
+ test_server:fail({received,Msg})
+ after 17 -> ok
+ end,
+ ok.
+
+getopt(S, Opt) ->
+ {ok,[{Opt,Val}]} = inet:getopts(S, [Opt]),
+ Val.
+
+getopt(S, Opt, Param) ->
+ {ok,[{Opt,Val}]} = inet:getopts(S, [{Opt,Param}]),
+ Val.
+
+setopt(S, Opt, Val) ->
+ inet:setopts(S, [{Opt,Val}]).
+
+ok({ok,X}) ->
+ io:format("OK: ~p~n", [X]),
+ X.
+
flush() ->
receive
Msg ->
@@ -382,3 +537,72 @@ api_connect_init(Config) when is_list(Config) ->
?line ok = gen_sctp:close(Sa),
?line ok = gen_sctp:close(Sb),
ok.
+
+api_opts(doc) ->
+ "Test socket options";
+api_opts(suite) ->
+ [];
+api_opts(Config) when is_list(Config) ->
+ ?line {ok,S} = gen_sctp:open(0),
+ ?line OSType = os:type(),
+ ?line case {inet:setopts(S, [{linger,{true,2}}]),OSType} of
+ {ok,_} ->
+ ok;
+ {{error,einval},{unix,sunos}} ->
+ ok
+ end.
+
+implicit_inet6(Config) when is_list(Config) ->
+ ?line Hostname = ok(inet:gethostname()),
+ ?line
+ case gen_sctp:open(0, [inet6]) of
+ {ok,S1} ->
+ ?line
+ case inet:getaddr(Hostname, inet6) of
+ {ok,Host} ->
+ ?line Loopback = {0,0,0,0,0,0,0,1},
+ ?line io:format("~s ~p~n", ["Loopback",Loopback]),
+ ?line implicit_inet6(S1, Loopback),
+ ?line ok = gen_sctp:close(S1),
+ %%
+ ?line Localhost =
+ ok(inet:getaddr("localhost", inet6)),
+ ?line io:format("~s ~p~n", ["localhost",Localhost]),
+ ?line S2 =
+ ok(gen_sctp:open(0, [{ip,Localhost}])),
+ ?line implicit_inet6(S2, Localhost),
+ ?line ok = gen_sctp:close(S2),
+ %%
+ ?line io:format("~s ~p~n", [Hostname,Host]),
+ ?line S3 =
+ ok(gen_sctp:open(0, [{ifaddr,Host}])),
+ ?line implicit_inet6(S3, Host),
+ ?line ok = gen_sctp:close(S1);
+ {error,eafnosupport} ->
+ ?line ok = gen_sctp:close(S1),
+ {skip,"Can not look up IPv6 address"}
+ end;
+ _ ->
+ {skip,"IPv6 not supported"}
+ end.
+
+implicit_inet6(S1, Addr) ->
+ ?line ok = gen_sctp:listen(S1, true),
+ ?line P1 = ok(inet:port(S1)),
+ ?line S2 = ok(gen_sctp:open(0, [inet6])),
+ ?line P2 = ok(inet:port(S2)),
+ ?line #sctp_assoc_change{state=comm_up} =
+ ok(gen_sctp:connect(S2, Addr, P1, [])),
+ ?line case ok(gen_sctp:recv(S1)) of
+ {Addr,P2,[],#sctp_assoc_change{state=comm_up}} ->
+ ok
+ end,
+ ?line case ok(inet:sockname(S1)) of
+ {Addr,P1} -> ok;
+ {{0,0,0,0,0,0,0,0},P1} -> ok
+ end,
+ ?line case ok(inet:sockname(S2)) of
+ {Addr,P2} -> ok;
+ {{0,0,0,0,0,0,0,0},P2} -> ok
+ end,
+ ?line ok = gen_sctp:close(S2).
diff --git a/lib/kernel/test/gen_tcp_api_SUITE.erl b/lib/kernel/test/gen_tcp_api_SUITE.erl
index 11d19aaa82..94637290a1 100644
--- a/lib/kernel/test/gen_tcp_api_SUITE.erl
+++ b/lib/kernel/test/gen_tcp_api_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -30,10 +30,11 @@
t_connect/1, t_connect_bad/1,
t_recv/1, t_recv_timeout/1, t_recv_eof/1,
t_shutdown_write/1, t_shutdown_both/1, t_shutdown_error/1,
- t_fdopen/1]).
+ t_fdopen/1, t_implicit_inet6/1]).
all(suite) -> [t_accept, t_connect, t_recv, t_shutdown_write,
- t_shutdown_both, t_shutdown_error, t_fdopen].
+ t_shutdown_both, t_shutdown_error, t_fdopen,
+ t_implicit_inet6].
init_per_testcase(_Func, Config) ->
Dog = test_server:timetrap(test_server:seconds(60)),
@@ -156,6 +157,54 @@ t_fdopen(Config) when is_list(Config) ->
ok.
+%%% implicit inet6 option to api functions
+
+t_implicit_inet6(Config) when is_list(Config) ->
+ ?line Hostname = ok(inet:gethostname()),
+ ?line
+ case gen_tcp:listen(0, [inet6]) of
+ {ok,S1} ->
+ ?line
+ case inet:getaddr(Hostname, inet6) of
+ {ok,Host} ->
+ ?line Loopback = {0,0,0,0,0,0,0,1},
+ ?line io:format("~s ~p~n", ["Loopback",Loopback]),
+ ?line implicit_inet6(S1, Loopback),
+ ?line ok = gen_tcp:close(S1),
+ %%
+ ?line Localhost =
+ ok(inet:getaddr("localhost", inet6)),
+ ?line io:format("~s ~p~n", ["localhost",Localhost]),
+ ?line S2 = ok(gen_tcp:listen(0, [{ip,Localhost}])),
+ ?line implicit_inet6(S2, Localhost),
+ ?line ok = gen_tcp:close(S2),
+ %%
+ ?line io:format("~s ~p~n", [Hostname,Host]),
+ ?line S3 = ok(gen_tcp:listen(0, [{ifaddr,Host}])),
+ ?line implicit_inet6(S3, Host),
+ ?line ok = gen_tcp:close(S1);
+ {error,eafnosupport} ->
+ ?line ok = gen_tcp:close(S1),
+ {skip,"Can not look up IPv6 address"}
+ end;
+ _ ->
+ {skip,"IPv6 not supported"}
+ end.
+
+implicit_inet6(S, Addr) ->
+ ?line P = ok(inet:port(S)),
+ ?line S2 = ok(gen_tcp:connect(Addr, P, [])),
+ ?line P2 = ok(inet:port(S2)),
+ ?line S1 = ok(gen_tcp:accept(S)),
+ ?line P1 = P = ok(inet:port(S1)),
+ ?line {Addr,P2} = ok(inet:peername(S1)),
+ ?line {Addr,P1} = ok(inet:peername(S2)),
+ ?line {Addr,P1} = ok(inet:sockname(S1)),
+ ?line {Addr,P2} = ok(inet:sockname(S2)),
+ ?line ok = gen_tcp:close(S2),
+ ?line ok = gen_tcp:close(S1).
+
+
%%% Utilities
@@ -217,3 +266,5 @@ unused_ip(A, B, C, D) ->
{ok, _} -> unused_ip(A, B, C, D+1);
{error, _} -> {ok, {A, B, C, D}}
end.
+
+ok({ok,V}) -> V.
diff --git a/lib/kernel/test/gen_tcp_misc_SUITE.erl b/lib/kernel/test/gen_tcp_misc_SUITE.erl
index 5d726a3b1b..d73c5fab56 100644
--- a/lib/kernel/test/gen_tcp_misc_SUITE.erl
+++ b/lib/kernel/test/gen_tcp_misc_SUITE.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
-module(gen_tcp_misc_SUITE).
@@ -957,12 +957,11 @@ http_bad_packet(Config) when is_list(Config) ->
http_worker(S) ->
case gen_tcp:recv(S, 0, 30000) of
+ {ok,{http_error,Error}} ->
+ io:format("Http error: ~s\n", [Error]);
{ok,Data} ->
io:format("Data: ~p\n", [Data]),
- http_worker(S);
- {error,Rsn} ->
- io:format("Error: ~p\n", [Rsn]),
- ok
+ http_worker(S)
end.
http_bad_client(Port) ->
diff --git a/lib/kernel/test/gen_udp_SUITE.erl b/lib/kernel/test/gen_udp_SUITE.erl
index fa1991872b..bbdfbd3cb0 100644
--- a/lib/kernel/test/gen_udp_SUITE.erl
+++ b/lib/kernel/test/gen_udp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -34,12 +34,12 @@
-export([send_to_closed/1,
buffer_size/1, binary_passive_recv/1, bad_address/1,
- read_packets/1, open_fd/1, connect/1]).
+ read_packets/1, open_fd/1, connect/1, implicit_inet6/1]).
all(suite) ->
[send_to_closed,
buffer_size, binary_passive_recv, bad_address, read_packets,
- open_fd, connect].
+ open_fd, connect, implicit_inet6].
init_per_testcase(_Case, Config) ->
?line Dog=test_server:timetrap(?default_timeout),
@@ -415,13 +415,67 @@ connect(suite) ->
connect(doc) ->
["Test that connect/3 has effect"];
connect(Config) when is_list(Config) ->
- Addr = {127,0,0,1},
- {ok,S1} = gen_udp:open(0),
- {ok,P1} = inet:port(S1),
- {ok,S2} = gen_udp:open(0),
- ok = inet:setopts(S2, [{active,false}]),
- ok = gen_udp:close(S1),
- ok = gen_udp:connect(S2, Addr, P1),
- ok = gen_udp:send(S2, <<16#deadbeef:32>>),
- {error,econnrefused} = gen_udp:recv(S2, 0, 5),
+ ?line Addr = {127,0,0,1},
+ ?line {ok,S1} = gen_udp:open(0),
+ ?line {ok,P1} = inet:port(S1),
+ ?line {ok,S2} = gen_udp:open(0),
+ ?line ok = inet:setopts(S2, [{active,false}]),
+ ?line ok = gen_udp:close(S1),
+ ?line ok = gen_udp:connect(S2, Addr, P1),
+ ?line ok = gen_udp:send(S2, <<16#deadbeef:32>>),
+ ?line {error,econnrefused} = gen_udp:recv(S2, 0, 5),
ok.
+
+implicit_inet6(Config) when is_list(Config) ->
+ ?line Hostname = ok(inet:gethostname()),
+ ?line Active = {active,false},
+ ?line
+ case gen_udp:open(0, [inet6,Active]) of
+ {ok,S1} ->
+ ?line
+ case inet:getaddr(Hostname, inet6) of
+ {ok,Host} ->
+ ?line Loopback = {0,0,0,0,0,0,0,1},
+ ?line io:format("~s ~p~n", ["Loopback",Loopback]),
+ ?line implicit_inet6(S1, Active, Loopback),
+ ?line ok = gen_udp:close(S1),
+ %%
+ ?line Localhost =
+ ok(inet:getaddr("localhost", inet6)),
+ ?line io:format("~s ~p~n", ["localhost",Localhost]),
+ ?line S2 =
+ ok(gen_udp:open(0, [{ip,Localhost},Active])),
+ ?line implicit_inet6(S2, Active, Localhost),
+ ?line ok = gen_udp:close(S2),
+ %%
+ ?line io:format("~s ~p~n", [Hostname,Host]),
+ ?line S3 =
+ ok(gen_udp:open(0, [{ifaddr,Host},Active])),
+ ?line implicit_inet6(S3, Active, Host),
+ ?line ok = gen_udp:close(S1);
+ {error,eafnosupport} ->
+ ?line ok = gen_udp:close(S1),
+ {skip,"Can not look up IPv6 address"}
+ end;
+ _ ->
+ {skip,"IPv6 not supported"}
+ end.
+
+implicit_inet6(S1, Active, Addr) ->
+ ?line P1 = ok(inet:port(S1)),
+ ?line S2 = ok(gen_udp:open(0, [inet6,Active])),
+ ?line P2 = ok(inet:port(S2)),
+ ?line ok = gen_udp:connect(S2, Addr, P1),
+ ?line ok = gen_udp:connect(S1, Addr, P2),
+ ?line {Addr,P2} = ok(inet:peername(S1)),
+ ?line {Addr,P1} = ok(inet:peername(S2)),
+ ?line {Addr,P1} = ok(inet:sockname(S1)),
+ ?line {Addr,P2} = ok(inet:sockname(S2)),
+ ?line ok = gen_udp:send(S1, Addr, P2, "ping"),
+ ?line {Addr,P1,"ping"} = ok(gen_udp:recv(S2, 1024, 1000)),
+ ?line ok = gen_udp:send(S2, Addr, P1, "pong"),
+ ?line {Addr,P2,"pong"} = ok(gen_udp:recv(S1, 1024)),
+ ?line ok = gen_udp:close(S2).
+
+
+ok({ok,V}) -> V.
diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl
index eb8f918491..ec05bf99b9 100644
--- a/lib/kernel/test/inet_SUITE.erl
+++ b/lib/kernel/test/inet_SUITE.erl
@@ -26,7 +26,8 @@
t_gethostbyaddr_v6/1, t_getaddr_v6/1, t_gethostbyname_v6/1,
ipv4_to_ipv6/1, host_and_addr/1, parse/1, t_gethostnative/1,
gethostnative_parallell/1, cname_loop/1,
- gethostnative_soft_restart/1,gethostnative_debug_level/1,getif/1]).
+ gethostnative_soft_restart/1,gethostnative_debug_level/1,getif/1,
+ getif_ifr_name_overflow/1,getservbyname_overflow/1,getifaddrs/1]).
-export([get_hosts/1, get_ipv6_hosts/1, parse_hosts/1, parse_address/1,
kill_gethost/0, parallell_gethost/0]).
@@ -39,7 +40,7 @@ all(suite) ->
ipv4_to_ipv6, host_and_addr, parse,t_gethostnative,
gethostnative_parallell, cname_loop,
gethostnative_debug_level,gethostnative_soft_restart,
- getif].
+ getif,getif_ifr_name_overflow,getservbyname_overflow,getifaddrs].
init_per_testcase(_Func, Config) ->
Dog = test_server:timetrap(test_server:seconds(60)),
@@ -872,10 +873,30 @@ getif(suite) ->
getif(doc) ->
["Tests basic functionality of getiflist, getif, and ifget"];
getif(Config) when is_list(Config) ->
+ ?line case os:type() of
+ {unix,Osname} ->
+ ?line do_getif(Osname);
+ {_,_} ->
+ {skip,"inet:getif/0 probably not supported"}
+ end.
+
+do_getif(Osname) ->
?line {ok,Hostname} = inet:gethostname(),
?line {ok,Address} = inet:getaddr(Hostname, inet),
?line {ok,Loopback} = inet:getaddr("localhost", inet),
?line {ok,Interfaces} = inet:getiflist(),
+ ?line HWAs =
+ lists:sort(
+ lists:foldl(
+ fun (I, Acc) ->
+ case inet:ifget(I, [hwaddr]) of
+ {ok,[{hwaddr,A}]} -> [A|Acc];
+ {ok,[]} -> Acc
+ end
+ end, [], Interfaces)),
+ ?line io:format("HWAs = ~p~n", [HWAs]),
+ ?line (Osname =/= sunos)
+ andalso ((length(HWAs) > 0) orelse (?t:fail(no_HWAs))),
?line Addresses =
lists:sort(
lists:foldl(
@@ -891,6 +912,134 @@ getif(Config) when is_list(Config) ->
?line true = ip_member(Loopback, Addresses),
?line ok.
+getif_ifr_name_overflow(doc) ->
+ "Test long interface names do not overrun buffer";
+getif_ifr_name_overflow(Config) when is_list(Config) ->
+ ?line case os:type() of
+ {unix,Osname} ->
+ ?line do_getif_ifr_name_overflow(Osname);
+ {_,_} ->
+ {skip,"inet:ifget/2 probably not supported"}
+ end.
+
+do_getif_ifr_name_overflow(_) ->
+ %% emulator should not crash
+ ?line {ok,[]} = inet:ifget(lists:duplicate(128, "x"), [addr]),
+ ok.
+
+getservbyname_overflow(doc) ->
+ "Test long service names do not overrun buffer";
+getservbyname_overflow(Config) when is_list(Config) ->
+ %% emulator should not crash
+ ?line {error,einval} = inet:getservbyname(list_to_atom(lists:flatten(lists:duplicate(128, "x"))), tcp),
+ ok.
+
+getifaddrs(doc) ->
+ "Test inet:gifaddrs/0";
+getifaddrs(Config) when is_list (Config) ->
+ ?line {ok,IfAddrs} = inet:getifaddrs(),
+ ?line ?t:format("IfAddrs = ~p.~n", [IfAddrs]),
+ ?line
+ case
+ {os:type(),
+ [If ||
+ {If,Opts} <- IfAddrs,
+ lists:keymember(hwaddr, 1, Opts)]} of
+ {{unix,sunos},[]} -> ok;
+ {OT,[]} ->
+ ?t:fail({should_have_hwaddr,OT});
+ _ -> ok
+ end,
+ ?line Addrs =
+ [element(1, A) || A <- ifaddrs(IfAddrs)],
+ ?line ?t:format("Addrs = ~p.~n", [Addrs]),
+ ?line [check_addr(Addr) || Addr <- Addrs],
+ ok.
+
+check_addr(Addr)
+ when tuple_size(Addr) =:= 8,
+ element(1, Addr) band 16#FFC0 =:= 16#FE80 ->
+ ?line ?t:format("Addr: ~p link local; SKIPPED!~n", [Addr]),
+ ok;
+check_addr(Addr) ->
+ ?line ?t:format("Addr: ~p.~n", [Addr]),
+ ?line Ping = "ping",
+ ?line Pong = "pong",
+ ?line {ok,L} = gen_tcp:listen(0, [{ip,Addr},{active,false}]),
+ ?line {ok,P} = inet:port(L),
+ ?line {ok,S1} = gen_tcp:connect(Addr, P, [{active,false}]),
+ ?line {ok,S2} = gen_tcp:accept(L),
+ ?line ok = gen_tcp:send(S2, Ping),
+ ?line {ok,Ping} = gen_tcp:recv(S1, length(Ping)),
+ ?line ok = gen_tcp:send(S1, Pong),
+ ?line ok = gen_tcp:close(S1),
+ ?line {ok,Pong} = gen_tcp:recv(S2, length(Pong)),
+ ?line ok = gen_tcp:close(S2),
+ ?line ok = gen_tcp:close(L),
+ ok.
+
+-record(ifopts, {name,flags,addrs=[],hwaddr}).
+
+ifaddrs([]) -> [];
+ifaddrs([{If,Opts}|IOs]) ->
+ ?line #ifopts{flags=Flags} = Ifopts =
+ check_ifopts(Opts, #ifopts{name=If}),
+ ?line case Flags =/= undefined andalso lists:member(up, Flags) of
+ true ->
+ Ifopts#ifopts.addrs;
+ false ->
+ []
+ end++ifaddrs(IOs).
+
+check_ifopts([], #ifopts{name=If,flags=Flags,addrs=Raddrs}=Ifopts) ->
+ Addrs = lists:reverse(Raddrs),
+ R = Ifopts#ifopts{addrs=Addrs},
+ ?t:format("~p.~n", [R]),
+ %% See how we did...
+ if is_list(Flags) -> ok;
+ true ->
+ ?t:fail({flags_undefined,If})
+ end,
+ case lists:member(broadcast, Flags) of
+ true ->
+ [case A of
+ {_,_,_} -> A;
+ {T,_} when tuple_size(T) =:= 8 -> A;
+ _ ->
+ ?t:fail({broaddr_missing,If,A})
+ end || A <- Addrs];
+ false ->
+ [case A of {_,_} -> A;
+ _ ->
+ ?t:fail({should_have_netmask,If,A})
+ end || A <- Addrs]
+ end,
+ R;
+check_ifopts([{flags,Flags}|Opts], #ifopts{flags=undefined}=Ifopts) ->
+ check_ifopts(Opts, Ifopts#ifopts{flags=Flags});
+check_ifopts([{flags,Fs}|Opts], #ifopts{flags=Flags}=Ifopts) ->
+ case Fs of
+ Flags ->
+ check_ifopts(Opts, Ifopts#ifopts{});
+ _ ->
+ ?t:fail({multiple_flags,Fs,Ifopts})
+ end;
+check_ifopts(
+ [{addr,Addr},{netmask,Netmask},{broadaddr,Broadaddr}|Opts],
+ #ifopts{addrs=Addrs}=Ifopts) ->
+ check_ifopts(Opts, Ifopts#ifopts{addrs=[{Addr,Netmask,Broadaddr}|Addrs]});
+check_ifopts(
+ [{addr,Addr},{netmask,Netmask}|Opts],
+ #ifopts{addrs=Addrs}=Ifopts) ->
+ check_ifopts(Opts, Ifopts#ifopts{addrs=[{Addr,Netmask}|Addrs]});
+check_ifopts([{addr,Addr}|Opts], #ifopts{addrs=Addrs}=Ifopts) ->
+ check_ifopts(Opts, Ifopts#ifopts{addrs=[{Addr}|Addrs]});
+check_ifopts([{hwaddr,Hwaddr}|Opts], #ifopts{hwaddr=undefined}=Ifopts)
+ when is_list(Hwaddr) ->
+ check_ifopts(Opts, Ifopts#ifopts{hwaddr=Hwaddr});
+check_ifopts([{hwaddr,HwAddr}|_], #ifopts{}=Ifopts) ->
+ ?t:fail({multiple_hwaddrs,HwAddr,Ifopts}).
+
%% Works just like lists:member/2, except that any {127,_,_,_} tuple
%% matches any other {127,_,_,_}. We do this to handle Linux systems
%% that use (for instance) 127.0.1.1 as the IP address for the hostname.
diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk
index 9a191f9aeb..03fe63e385 100644
--- a/lib/kernel/vsn.mk
+++ b/lib/kernel/vsn.mk
@@ -1,20 +1 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2010. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-#
-
-KERNEL_VSN = 2.14.1
+KERNEL_VSN = 2.14.2
diff --git a/lib/megaco/doc/src/notes.xml b/lib/megaco/doc/src/notes.xml
index af6e87b56b..81c9305542 100644
--- a/lib/megaco/doc/src/notes.xml
+++ b/lib/megaco/doc/src/notes.xml
@@ -35,7 +35,22 @@
thus constitutes one section in this document. The title of each
section is the version number of Megaco.</p>
- <section>
+ <section><title>Megaco 3.15</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Fixing auto-import issues.</p>
+ <p>
+ Own Id: OTP-8842</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section>
<title>Megaco 3.14.1.1</title>
<p>Version 3.14.1.1 supports code replacement in runtime from/to
diff --git a/lib/megaco/examples/meas/megaco_codec_meas.erl b/lib/megaco/examples/meas/megaco_codec_meas.erl
index 88b34105ac..51ee396338 100644
--- a/lib/megaco/examples/meas/megaco_codec_meas.erl
+++ b/lib/megaco/examples/meas/megaco_codec_meas.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -43,6 +43,8 @@
%% API
+%% Avoid warning for local function error/2 clashing with autoimported BIF.
+-compile({no_auto_import,[error/2]}).
-export([start/0, start/1]).
-export([start1/0]).
diff --git a/lib/megaco/examples/meas/megaco_codec_mstone_lib.erl b/lib/megaco/examples/meas/megaco_codec_mstone_lib.erl
index 31df945777..040af9826b 100644
--- a/lib/megaco/examples/meas/megaco_codec_mstone_lib.erl
+++ b/lib/megaco/examples/meas/megaco_codec_mstone_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -26,6 +26,8 @@
%% API
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([start_flex_scanner/0, stop_flex_scanner/1,
expanded_messages/2, expanded_messages/3,
set_default_sched_bind/0,
diff --git a/lib/megaco/src/app/megaco.appup.src b/lib/megaco/src/app/megaco.appup.src
index d904e8ab33..66068f650f 100644
--- a/lib/megaco/src/app/megaco.appup.src
+++ b/lib/megaco/src/app/megaco.appup.src
@@ -130,100 +130,53 @@
%% |
%% v
%% 3.14.1.1
+%% |
+%% v
+%% 3.15
%%
%%
{"%VSN%",
[
- {"3.14.1",
- [
- ]
- },
- {"3.14",
- [
- {load_module, megaco_messenger, soft_purge, soft_purge, [megaco_monitor]},
- {update, megaco_monitor, soft, soft_purge, soft_purge, []},
- {update, megaco_config, soft, soft_purge, soft_purge, []}
- ]
- },
- {"3.13",
- [
- {load_module, megaco_messenger, soft_purge, soft_purge, [megaco_monitor]},
- {load_module, megaco_filter, soft_purge, soft_purge, []},
- {update, megaco_monitor, soft, soft_purge, soft_purge, []},
- {update, megaco_config, soft, soft_purge, soft_purge, []},
- {update, megaco_flex_scanner_handler, {advanced, downgrade_to_pre_3_13_1},
- soft_purge, soft_purge, []}
- ]
- },
- {"3.12",
- [
- {load_module, megaco_filter, soft_purge, soft_purge, []},
- {load_module, megaco_udp, soft_purge, soft_purge, []},
- {load_module, megaco_messenger, soft_purge, soft_purge, [megaco_monitor]},
- {update, megaco_config, soft, soft_purge, soft_purge, []},
- {update, megaco_monitor, soft, soft_purge, soft_purge, []},
- {update, megaco_flex_scanner_handler, {advanced, downgrade_to_pre_3_13_1},
- soft_purge, soft_purge, []}
- ]
- },
- {"3.11.3",
+ {"3.14.1.1",
[
- {load_module, megaco_filter, soft_purge, soft_purge, []},
- {load_module, megaco_udp, soft_purge, soft_purge, []},
- {load_module, megaco_messenger, soft_purge, soft_purge,
- [megaco_config, megaco_monitor]},
- {update, megaco_monitor, soft, soft_purge, soft_purge, []},
- {update, megaco_config, {advanced, upgrade_from_pre_3_12},
- soft_purge, soft_purge, []},
- {update, megaco_flex_scanner_handler, {advanced, downgrade_to_pre_3_13_1},
- soft_purge, soft_purge, []}
+ {load_module, megaco_binary_transformer_prev3a, soft_purge, soft_purge, []},
+ {load_module, megaco_binary_transformer_prev3b, soft_purge, soft_purge, []},
+ {load_module, megaco_binary_transformer_prev3c, soft_purge, soft_purge, []},
+ {load_module, megaco_sdp, soft_purge, soft_purge, []},
+ {load_module, megaco_compact_text_encoder_v1, soft_purge, soft_purge, []},
+ {load_module, megaco_pretty_text_encoder_v1, soft_purge, soft_purge, []},
+ {load_module, megaco_compact_text_encoder_v2, soft_purge, soft_purge, []},
+ {load_module, megaco_pretty_text_encoder_v2, soft_purge, soft_purge, []},
+ {load_module, megaco_compact_text_encoder_prev3a, soft_purge, soft_purge, []},
+ {load_module, megaco_pretty_text_encoder_prev3a, soft_purge, soft_purge, []},
+ {load_module, megaco_compact_text_encoder_prev3b, soft_purge, soft_purge, []},
+ {load_module, megaco_pretty_text_encoder_prev3b, soft_purge, soft_purge, []},
+ {load_module, megaco_compact_text_encoder_prev3c, soft_purge, soft_purge, []},
+ {load_module, megaco_pretty_text_encoder_prev3c, soft_purge, soft_purge, []},
+ {load_module, megaco_compact_text_encoder_v3, soft_purge, soft_purge, []},
+ {load_module, megaco_pretty_text_encoder_v3, soft_purge, soft_purge, []}
]
}
],
[
- {"3.14.1",
- [
- ]
- },
- {"3.14",
- [
- {load_module, megaco_messenger, soft_purge, soft_purge, [megaco_monitor]},
- {update, megaco_monitor, soft, soft_purge, soft_purge, []},
- {update, megaco_config, soft, soft_purge, soft_purge, []}
- ]
- },
- {"3.13",
- [
- {load_module, megaco_messenger, soft_purge, soft_purge, [megaco_monitor]},
- {load_module, megaco_filter, soft_purge, soft_purge, []},
- {update, megaco_monitor, soft, soft_purge, soft_purge, []},
- {update, megaco_config, soft, soft_purge, soft_purge, []},
- {update, megaco_flex_scanner_handler, {advanced, upgrade_from_pre_3_13_1},
- soft_purge, soft_purge, []}
- ]
- },
- {"3.12",
- [
- {load_module, megaco_filter, soft_purge, soft_purge, []},
- {load_module, megaco_udp, soft_purge, soft_purge, []},
- {load_module, megaco_messenger, soft_purge, soft_purge, [megaco_monitor]},
- {update, megaco_config, soft, soft_purge, soft_purge, []},
- {update, megaco_monitor, soft, soft_purge, soft_purge, []},
- {update, megaco_flex_scanner_handler, {advanced, upgrade_from_pre_3_13_1},
- soft_purge, soft_purge, []}
- ]
- },
- {"3.11.3",
+ {"3.14.1.1",
[
- {load_module, megaco_filter, soft_purge, soft_purge, []},
- {load_module, megaco_udp, soft_purge, soft_purge, []},
- {load_module, megaco_messenger, soft_purge, soft_purge,
- [megaco_config, megaco_monitor]},
- {update, megaco_monitor, soft, soft_purge, soft_purge, []},
- {update, megaco_config, {advanced, downgrade_to_pre_3_12},
- soft_purge, soft_purge, []},
- {update, megaco_flex_scanner_handler, {advanced, upgrade_from_pre_3_13_1},
- soft_purge, soft_purge, []}
+ {load_module, megaco_binary_transformer_prev3a, soft_purge, soft_purge, []},
+ {load_module, megaco_binary_transformer_prev3b, soft_purge, soft_purge, []},
+ {load_module, megaco_binary_transformer_prev3c, soft_purge, soft_purge, []},
+ {load_module, megaco_sdp, soft_purge, soft_purge, []},
+ {load_module, megaco_compact_text_encoder_v1, soft_purge, soft_purge, []},
+ {load_module, megaco_pretty_text_encoder_v1, soft_purge, soft_purge, []},
+ {load_module, megaco_compact_text_encoder_v2, soft_purge, soft_purge, []},
+ {load_module, megaco_pretty_text_encoder_v2, soft_purge, soft_purge, []},
+ {load_module, megaco_compact_text_encoder_prev3a, soft_purge, soft_purge, []},
+ {load_module, megaco_pretty_text_encoder_prev3a, soft_purge, soft_purge, []},
+ {load_module, megaco_compact_text_encoder_prev3b, soft_purge, soft_purge, []},
+ {load_module, megaco_pretty_text_encoder_prev3b, soft_purge, soft_purge, []},
+ {load_module, megaco_compact_text_encoder_prev3c, soft_purge, soft_purge, []},
+ {load_module, megaco_pretty_text_encoder_prev3c, soft_purge, soft_purge, []},
+ {load_module, megaco_compact_text_encoder_v3, soft_purge, soft_purge, []},
+ {load_module, megaco_pretty_text_encoder_v3, soft_purge, soft_purge, []}
]
}
]
diff --git a/lib/megaco/src/binary/megaco_binary_transformer_prev3a.erl b/lib/megaco/src/binary/megaco_binary_transformer_prev3a.erl
index 609947c933..ba4324f4f2 100644
--- a/lib/megaco/src/binary/megaco_binary_transformer_prev3a.erl
+++ b/lib/megaco/src/binary/megaco_binary_transformer_prev3a.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1619,11 +1619,3 @@ verify_count(Count, Min, Max) ->
true ->
error({count_not_an_integer, Count})
end.
-
-
-%% -------------------------------------------------------------------
-
-error(Reason) ->
- erlang:error(Reason).
-
-
diff --git a/lib/megaco/src/binary/megaco_binary_transformer_prev3b.erl b/lib/megaco/src/binary/megaco_binary_transformer_prev3b.erl
index baca84bbfe..8e42353b9b 100644
--- a/lib/megaco/src/binary/megaco_binary_transformer_prev3b.erl
+++ b/lib/megaco/src/binary/megaco_binary_transformer_prev3b.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1619,11 +1619,3 @@ verify_count(Count, Min, Max) ->
true ->
error({count_not_an_integer, Count})
end.
-
-
-%% -------------------------------------------------------------------
-
-error(Reason) ->
- erlang:error(Reason).
-
-
diff --git a/lib/megaco/src/binary/megaco_binary_transformer_prev3c.erl b/lib/megaco/src/binary/megaco_binary_transformer_prev3c.erl
index 8d2f9eea38..c26d1fa99d 100644
--- a/lib/megaco/src/binary/megaco_binary_transformer_prev3c.erl
+++ b/lib/megaco/src/binary/megaco_binary_transformer_prev3c.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1746,11 +1746,3 @@ verify_count(Count, Min, Max) ->
true ->
error({count_not_an_integer, Count})
end.
-
-
-%% -------------------------------------------------------------------
-
-error(Reason) ->
- erlang:error(Reason).
-
-
diff --git a/lib/megaco/src/binary/megaco_binary_transformer_v3.erl b/lib/megaco/src/binary/megaco_binary_transformer_v3.erl
index cef49b03fd..1ff7c86e82 100644
--- a/lib/megaco/src/binary/megaco_binary_transformer_v3.erl
+++ b/lib/megaco/src/binary/megaco_binary_transformer_v3.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1753,11 +1753,3 @@ verify_count(Count, Min, Max) ->
true ->
error({count_not_an_integer, Count})
end.
-
-
-%% -------------------------------------------------------------------
-
-error(Reason) ->
- erlang:error(Reason).
-
-
diff --git a/lib/megaco/src/engine/megaco_sdp.erl b/lib/megaco/src/engine/megaco_sdp.erl
index 90911fe24a..37f28cac59 100644
--- a/lib/megaco/src/engine/megaco_sdp.erl
+++ b/lib/megaco/src/engine/megaco_sdp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -38,6 +38,8 @@
%% External exports
%%----------------------------------------------------------------------
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([
decode/1, encode/1,
get_sdp_record_from_PropertyGroup/2
diff --git a/lib/megaco/src/text/megaco_text_gen_prev3a.hrl b/lib/megaco/src/text/megaco_text_gen_prev3a.hrl
index b1ddb10a4e..81916cb9ec 100644
--- a/lib/megaco/src/text/megaco_text_gen_prev3a.hrl
+++ b/lib/megaco/src/text/megaco_text_gen_prev3a.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -2924,10 +2924,6 @@ verify_count(Count, Min, Max) ->
end.
-%% -------------------------------------------------------------------
-
-error(Reason) ->
- erlang:error(Reason).
%% -------------------------------------------------------------------
diff --git a/lib/megaco/src/text/megaco_text_gen_prev3b.hrl b/lib/megaco/src/text/megaco_text_gen_prev3b.hrl
index 8a4af877dc..83d25c83c9 100644
--- a/lib/megaco/src/text/megaco_text_gen_prev3b.hrl
+++ b/lib/megaco/src/text/megaco_text_gen_prev3b.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -2945,10 +2945,6 @@ verify_count(Count, Min, Max) ->
end.
-%% -------------------------------------------------------------------
-
-error(Reason) ->
- erlang:error(Reason).
%% -------------------------------------------------------------------
diff --git a/lib/megaco/src/text/megaco_text_gen_prev3c.hrl b/lib/megaco/src/text/megaco_text_gen_prev3c.hrl
index 11db906846..458809ca75 100644
--- a/lib/megaco/src/text/megaco_text_gen_prev3c.hrl
+++ b/lib/megaco/src/text/megaco_text_gen_prev3c.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -3421,10 +3421,6 @@ verify_count(Count, Min, Max) ->
end.
-%% -------------------------------------------------------------------
-
-error(Reason) ->
- erlang:error(Reason).
%% -------------------------------------------------------------------
diff --git a/lib/megaco/src/text/megaco_text_gen_v1.hrl b/lib/megaco/src/text/megaco_text_gen_v1.hrl
index b150c9ba58..0726d68941 100644
--- a/lib/megaco/src/text/megaco_text_gen_v1.hrl
+++ b/lib/megaco/src/text/megaco_text_gen_v1.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -2386,10 +2386,6 @@ verify_count(Count, Min, Max) ->
end.
-%% -------------------------------------------------------------------
-
-error(Reason) ->
- erlang:error(Reason).
% d(F) ->
% d(F, []).
diff --git a/lib/megaco/src/text/megaco_text_gen_v2.hrl b/lib/megaco/src/text/megaco_text_gen_v2.hrl
index 6cfcac8664..8e12efe65a 100644
--- a/lib/megaco/src/text/megaco_text_gen_v2.hrl
+++ b/lib/megaco/src/text/megaco_text_gen_v2.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -2772,10 +2772,6 @@ verify_count(Count, Min, Max) ->
end.
-%% -------------------------------------------------------------------
-
-error(Reason) ->
- erlang:error(Reason).
%% -------------------------------------------------------------------
diff --git a/lib/megaco/src/text/megaco_text_gen_v3.hrl b/lib/megaco/src/text/megaco_text_gen_v3.hrl
index 1c19a4aa8b..ce2e5e508d 100644
--- a/lib/megaco/src/text/megaco_text_gen_v3.hrl
+++ b/lib/megaco/src/text/megaco_text_gen_v3.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -3436,10 +3436,6 @@ verify_count(Count, Min, Max) ->
end.
-%% -------------------------------------------------------------------
-
-error(Reason) ->
- erlang:error(Reason).
%% -------------------------------------------------------------------
diff --git a/lib/megaco/vsn.mk b/lib/megaco/vsn.mk
index efb46253aa..9fc0e0f2fa 100644
--- a/lib/megaco/vsn.mk
+++ b/lib/megaco/vsn.mk
@@ -1,151 +1,4 @@
-#-*-makefile-*- ; force emacs to enter makefile-mode
-
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2001-2010. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-
APPLICATION = megaco
-MEGACO_VSN = 3.14.1.1
+MEGACO_VSN = 3.15
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(MEGACO_VSN)$(PRE_VSN)"
-
-TICKETS = OTP-8696
-
-TICKETS_3_14_1 = OTP-8529 OTP-8561 OTP-8627 OTP-8634
-
-TICKETS_3_14 = OTP-8317 OTP-8323 OTP-8328 OTP-8362 OTP-8403
-
-TICKETS_3_13 = OTP-8205 OTP-8239 OTP-8249
-
-TICKETS_3_12 = OTP-8183 OTP-8212
-
-TICKETS_3_11_3 = OTP-8164 OTP-8167 OTP-8191
-
-TICKETS_3_11_2 = OTP-8123
-
-TICKETS_3_11_1 = OTP-8081 OTP-8114
-
-TICKETS_3_11 = OTP-7302 OTP-7995
-
-TICKETS_3_10_1 = OTP-7926 OTP-7936
-
-TICKETS_3_10_0_1 = OTP-7851
-
-TICKETS_3_10 = OTP-7713 OTP-7743
-
-TICKETS_3_9_4 = OTP-7728 OTP-7733
-
-TICKETS_3_9_3 = OTP-7700
-
-TICKETS_3_9_2 = OTP-7671 OTP-7672
-
-TICKETS_3_9_1_1 = OTP-7614
-
-TICKETS_3_9_1 = OTP-7572 OTP-7573 OTP-7576
-
-TICKETS_3_9 = OTP-7431
-
-TICKETS_3_8_2 = OTP-7534
-
-TICKETS_3_8_1 = OTP-7398 OTP-7417 OTP-7444 OTP-7449 OTP-7455 OTP-7457 OTP-7459
-
-TICKETS_3_8 = OTP-7192 OTP-7228 OTP-7259
-
-TICKETS_3_7_5 = OTP-7286 OTP-7303
-
-TICKETS_3_7_4 = OTP-7249 OTP-7251
-
-TICKETS_3_7_3 = OTP-7168 OTP-7180 OTP-7189 OTP-7216
-
-TICKETS_3_7_2 = OTP-6972 OTP-7138
-
-TICKETS_3_7_1 = OTP-6919 OTP-6971 OTP-6992 OTP-6999 OTP-7000 OTP-7005 OTP-7124
-
-TICKETS_3_7 = OTP-5979 OTP-6753 OTP-6804 OTP-6865 OTP-6919 OTP-6976
-
-TICKETS_3_6_2 = OTP-6921
-
-TICKETS_3_6_1 = OTP-6803
-
-TICKETS_3_6_0_1 = OTP-6704
-
-TICKETS_3_6 = OTP-6185 OTP-6578 OTP-6441 OTP-6442 OTP-6544 OTP-6605 OTP-6609
-
-TICKETS_3_5_3 = OTP-6520 OTP-6549
-
-TICKETS_3_5_2 = OTP-6404 OTP-6422 OTP-6490 OTP-6503
-
-TICKETS_3_5_1 = OTP-6275 OTP-6276
-
-TICKETS_3_5 = OTP-6223 OTP-6253 OTP-6256
-
-TICKETS_3_4_4 = OTP-6181 OTP-6182 OTP-6217 OTP-6219
-
-TICKETS_3_4_3 = OTP-6170 OTP-6171 OTP-6172
-
-TICKETS_3_4_2 = OTP-6148
-
-TICKETS_3_4_1 = OTP-6113
-
-TICKETS_3_4 = \
- OTP-5769 \
- OTP-5980 \
- OTP-6009 \
- OTP-6025 \
- OTP-6028 \
- OTP-6030 \
- OTP-6048 \
- OTP-6051 \
- OTP-6052 \
- OTP-6055 \
- OTP-6089 \
- OTP-6090
-
-TICKETS_3_3_5 = OTP-6108
-
-TICKETS_3_3_4 = OTP-6076
-
-TICKETS_3_3_3 = OTP-6046
-
-TICKETS_3_3_2 = OTP-6017 OTP-6022
-
-TICKETS_3_3_1 = OTP-5993
-
-TICKETS_3_3 = OTP-5965 OTP-5973
-
-TICKETS_3_2_7 = OTP-5948 OTP-5952 OTP-5953
-
-TICKETS_3_2_6 = OTP-5918 OTP-5919 OTP-5920
-
-TICKETS_3_2_5 = OTP-5887
-
-TICKETS_3_2_4 = OTP-5867 OTP-5879 OTP-5880 OTP-5881 OTP-5882 OTP-5885 OTP-5886
-
-TICKETS_3_2_3 = OTP-5826 OTP-5830 OTP-5833 OTP-5836 OTP-5839
-
-TICKETS_3_2_2 = OTP-5799 OTP-5803 OTP-5804 OTP-5805 OTP-5816
-
-TICKETS_3_2_1 = OTP-5725 OTP-5793
-
-TICKETS_3_2 = OTP-5717 OTP-5750
-
-TICKETS_3_1 = OTP-5542 OTP-5597 OTP-5600 OTP-5601 OTP-5619 OTP-5664
-
-TICKETS_3_0_1 = \
- OTP-5401 \
- OTP-5446 \
- OTP-5447
-
diff --git a/lib/mnesia/doc/src/notes.xml b/lib/mnesia/doc/src/notes.xml
index b0bead0ba0..2352f11b93 100644
--- a/lib/mnesia/doc/src/notes.xml
+++ b/lib/mnesia/doc/src/notes.xml
@@ -38,7 +38,22 @@
thus constitutes one section in this document. The title of each
section is the version number of Mnesia.</p>
- <section><title>Mnesia 4.4.14</title>
+ <section><title>Mnesia 4.4.15</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Eliminated warnings for auto-imported BIF clashes.</p>
+ <p>
+ Own Id: OTP-8840</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Mnesia 4.4.14</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/mnesia/src/mnesia_controller.erl b/lib/mnesia/src/mnesia_controller.erl
index 0298b382a6..021be8af2a 100644
--- a/lib/mnesia/src/mnesia_controller.erl
+++ b/lib/mnesia/src/mnesia_controller.erl
@@ -98,6 +98,8 @@
connect_nodes2/3
]).
+-compile({no_auto_import,[error/2]}).
+
-import(mnesia_lib, [set/2, add/2]).
-import(mnesia_lib, [fatal/2, error/2, verbose/2, dbg_out/2]).
diff --git a/lib/mnesia/src/mnesia_locker.erl b/lib/mnesia/src/mnesia_locker.erl
index cfa3f171b2..6b5770d91e 100644
--- a/lib/mnesia/src/mnesia_locker.erl
+++ b/lib/mnesia/src/mnesia_locker.erl
@@ -49,6 +49,8 @@
system_code_change/4
]).
+-compile({no_auto_import,[error/2]}).
+
-include("mnesia.hrl").
-import(mnesia_lib, [dbg_out/2, error/2, verbose/2]).
diff --git a/lib/mnesia/src/mnesia_log.erl b/lib/mnesia/src/mnesia_log.erl
index 00ec4740ee..11b792026e 100644
--- a/lib/mnesia/src/mnesia_log.erl
+++ b/lib/mnesia/src/mnesia_log.erl
@@ -182,6 +182,8 @@
]).
+-compile({no_auto_import,[error/2]}).
+
-include("mnesia.hrl").
-import(mnesia_lib, [val/1, dir/1]).
-import(mnesia_lib, [exists/1, fatal/2, error/2, dbg_out/2]).
diff --git a/lib/mnesia/src/mnesia_monitor.erl b/lib/mnesia/src/mnesia_monitor.erl
index 5bd93d6b9b..b6eda9ad3a 100644
--- a/lib/mnesia/src/mnesia_monitor.erl
+++ b/lib/mnesia/src/mnesia_monitor.erl
@@ -70,6 +70,8 @@
negotiate_protocol_impl/2
]).
+-compile({no_auto_import,[error/2]}).
+
-import(mnesia_lib, [dbg_out/2, verbose/2, error/2, fatal/2, set/2]).
-include("mnesia.hrl").
diff --git a/lib/mnesia/src/mnesia_recover.erl b/lib/mnesia/src/mnesia_recover.erl
index 0ca7bf3f7f..7435b6896a 100644
--- a/lib/mnesia/src/mnesia_recover.erl
+++ b/lib/mnesia/src/mnesia_recover.erl
@@ -62,6 +62,7 @@
code_change/3
]).
+-compile({no_auto_import,[error/2]}).
-include("mnesia.hrl").
-import(mnesia_lib, [set/2, verbose/2, error/2, fatal/2]).
diff --git a/lib/mnesia/src/mnesia_registry.erl b/lib/mnesia/src/mnesia_registry.erl
index 9805d48697..202689ae5e 100644
--- a/lib/mnesia/src/mnesia_registry.erl
+++ b/lib/mnesia/src/mnesia_registry.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -65,6 +65,8 @@
%%%----------------------------------------------------------------------
%% External exports
+%% Avoid warning for local function max/2 clashing with autoimported BIF.
+-compile({no_auto_import,[max/2]}).
-export([start_dump/2, start_restore/2]).
-export([create_table/1, create_table/2]).
diff --git a/lib/mnesia/src/mnesia_subscr.erl b/lib/mnesia/src/mnesia_subscr.erl
index 93d4a86f7f..415c69d508 100644
--- a/lib/mnesia/src/mnesia_subscr.erl
+++ b/lib/mnesia/src/mnesia_subscr.erl
@@ -43,6 +43,8 @@
code_change/3
]).
+-compile({no_auto_import,[error/2]}).
+
-include("mnesia.hrl").
-import(mnesia_lib, [error/2]).
diff --git a/lib/mnesia/src/mnesia_text.erl b/lib/mnesia/src/mnesia_text.erl
index f1a28bf43d..ab1362f6b6 100644
--- a/lib/mnesia/src/mnesia_text.erl
+++ b/lib/mnesia/src/mnesia_text.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -20,6 +20,8 @@
%%
-module(mnesia_text).
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([parse/1, file/1, load_textfile/1, dump_to_textfile/1]).
load_textfile(File) ->
diff --git a/lib/mnesia/test/Makefile b/lib/mnesia/test/Makefile
index a4f32e3f78..4f98efaed1 100644
--- a/lib/mnesia/test/Makefile
+++ b/lib/mnesia/test/Makefile
@@ -109,7 +109,7 @@ release_spec: opt
release_tests_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) mnesia.spec mnesia.spec.vxworks $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)
- $(INSTALL_PROGRAM) mt $(INSTALL_PROGS) $(RELSYSDIR)
+ $(INSTALL_SCRIPT) mt $(INSTALL_PROGS) $(RELSYSDIR)
# chmod -f -R u+w $(RELSYSDIR)
# @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
diff --git a/lib/mnesia/vsn.mk b/lib/mnesia/vsn.mk
index 2780b737b6..bce0f7b739 100644
--- a/lib/mnesia/vsn.mk
+++ b/lib/mnesia/vsn.mk
@@ -1,17 +1 @@
-
-MNESIA_VSN = 4.4.14
-
-TICKETS = OTP-8519
-#TICKETS_4.4.13 = OTP-8402 OTP-8406
-#TICKETS_4.4.12 = OTP-8250
-#TICKETS_4.4.11 = OTP-8074
-#TICKETS_4.4.10 = OTP-7928 OTP-7968 OTP-8002
-#TICKETS_4.4.9 = OTP-7911
-#TICKETS_4.4.8 = OTP-7753 OTP-7835
-#TICKETS_4.4.7 = OTP-7524 OTP-7625
-#TICKETS_4.4.6 = OTP-7585
-#TICKETS_4.4.5 = OTP-7466
-#TICKETS_4.4.4 = OTP-7419
-#TICKETS_4.4.3 = OTP-7340 OTP-7378 OTP-7383
-#TICKETS_4.4.2 = OTP-7205 OTP-7208
-#TICKETS_4.4.1 = OTP-7170
+MNESIA_VSN = 4.4.15
diff --git a/lib/observer/src/Makefile b/lib/observer/src/Makefile
index dde1ea17be..b4eb518dd7 100644
--- a/lib/observer/src/Makefile
+++ b/lib/observer/src/Makefile
@@ -111,7 +111,8 @@ release_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)/src
$(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR)/src
$(INSTALL_DATA) $(INTERNAL_HRL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(EXAMPLE_FILES) $(RELSYSDIR)/src
+ $(INSTALL_DIR) $(RELSYSDIR)/examples
+ $(INSTALL_DATA) $(EXAMPLE_FILES) $(RELSYSDIR)/examples
$(INSTALL_DIR) $(RELSYSDIR)/include
$(INSTALL_DATA) $(HRL_FILES) $(RELSYSDIR)/include
$(INSTALL_DIR) $(RELSYSDIR)/ebin
diff --git a/lib/odbc/c_src/odbcserver.c b/lib/odbc/c_src/odbcserver.c
index c9627e9d05..077d78bfe5 100644
--- a/lib/odbc/c_src/odbcserver.c
+++ b/lib/odbc/c_src/odbcserver.c
@@ -108,8 +108,8 @@
#if defined WIN32
#include <winsock2.h>
-/* #include <ws2tcpip.h > When we can support a newer c-compiler*/
#include <windows.h>
+#include <ws2tcpip.h >
#include <fcntl.h>
#include <sql.h>
#include <sqlext.h>
@@ -1599,7 +1599,7 @@ static Boolean decode_params(db_state *state, byte *buffer, int *index, param_ar
break;
case SQL_C_TYPE_TIMESTAMP:
ts = (TIMESTAMP_STRUCT*) param->values.string;
- ei_decode_tuple_header(buffer, index, &val);
+ ei_decode_tuple_header(buffer, index, &size);
ei_decode_long(buffer, index, &val);
ts[j].year = (SQLUSMALLINT)val;
ei_decode_long(buffer, index, &val);
@@ -1727,74 +1727,48 @@ static byte * receive_erlang_port_msg(void)
}
/* ------------- Socket communication functions --------------------------*/
-#define USE_IPV4
-#ifdef UNIX
-#define SOCKET int
-#endif
-#if defined WIN32 || defined USE_IPV4
-/* Currently only an old windows compiler is supported so we do not have ipv6
- capabilities */
+#if defined(WIN32)
static SOCKET connect_to_erlang(const char *port)
-{
- SOCKET sock;
- struct sockaddr_in sin;
-
- sock = socket(AF_INET, SOCK_STREAM, 0);
-
- memset(&sin, 0, sizeof(sin));
- sin.sin_port = htons ((unsigned short)atoi(port));
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = inet_addr("127.0.0.1");
-
- if (connect(sock, (struct sockaddr*)&sin, sizeof(sin)) != 0) {
- close_socket(sock);
- DO_EXIT(EXIT_SOCKET_CONNECT);
- }
- return sock;
-}
#elif defined(UNIX)
static int connect_to_erlang(const char *port)
+#endif
{
- int sock;
-
- struct addrinfo hints;
- struct addrinfo *erlang_ai, *first;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC; /* PF_INET or PF_INET6 */
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
-
- if (getaddrinfo("localhost", port, &hints, &first) != 0) {
- DO_EXIT(EXIT_FAILURE);
- }
+#if defined(WIN32)
+ SOCKET sock;
+#elif defined(UNIX)
+ int sock;
+#endif
+ struct sockaddr_in sin;
+
+#if defined(HAVE_STRUCT_SOCKADDR_IN6_SIN6_ADDR) && defined(AF_INET6)
+ struct sockaddr_in6 sin6;
+
+ sock = socket(AF_INET6, SOCK_STREAM, 0);
+
+ memset(&sin6, 0, sizeof(sin6));
+ sin6.sin6_port = htons ((unsigned short)atoi(port));
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_addr = in6addr_loopback;
- for (erlang_ai = first; erlang_ai; erlang_ai = erlang_ai->ai_next) {
+ if (connect(sock, (struct sockaddr*)&sin6, sizeof(sin6)) == 0) {
+ return sock;
+ }
+ close_socket(sock);
+#endif
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_port = htons ((unsigned short)atoi(port));
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- sock = socket(erlang_ai->ai_family, erlang_ai->ai_socktype,
- erlang_ai->ai_protocol);
- if (sock < 0)
- continue;
- if (connect(sock, (struct sockaddr*)erlang_ai->ai_addr,
- erlang_ai->ai_addrlen) < 0) {
- close(sock);
- sock = -1;
- continue;
- } else {
- break;
+ if (connect(sock, (struct sockaddr*)&sin, sizeof(sin)) != 0) {
+ close_socket(sock);
+ DO_EXIT(EXIT_SOCKET_CONNECT);
}
- }
- freeaddrinfo(first);
-
- if (sock < 0){
- close_socket(sock);
- DO_EXIT(EXIT_SOCKET_CONNECT);
- }
-
- return sock;
+ return sock;
}
-#endif
#ifdef WIN32
static void close_socket(SOCKET socket)
@@ -2177,9 +2151,9 @@ static void init_param_column(param_array *params, byte *buffer, int *index,
params->type.sql = SQL_TYPE_TIMESTAMP;
params->type.len = sizeof(TIMESTAMP_STRUCT);
params->type.c = SQL_C_TYPE_TIMESTAMP;
- params->type.col_size = (SQLUINTEGER)19;//;sizeof(TIMESTAMP_STRUCT);
+ params->type.col_size = (SQLUINTEGER)COL_SQL_TIMESTAMP;
params->values.string =
- (TIMESTAMP_STRUCT *)safe_malloc(num_param_values * params->type.len);
+ (byte *)safe_malloc(num_param_values * params->type.len);
break;
case USER_FLOAT:
params->type.sql = SQL_FLOAT;
diff --git a/lib/odbc/c_src/odbcserver.h b/lib/odbc/c_src/odbcserver.h
index e6d8df1f58..3e2b22ab7d 100644
--- a/lib/odbc/c_src/odbcserver.h
+++ b/lib/odbc/c_src/odbcserver.h
@@ -98,6 +98,7 @@
#define COL_SQL_REAL 7
#define COL_SQL_DOUBLE 15
#define COL_SQL_TINYINT 4
+#define COL_SQL_TIMESTAMP 19
/* Types of parameters given to param_query*/
#define USER_SMALL_INT 1
diff --git a/lib/odbc/configure.in b/lib/odbc/configure.in
index 94e8a214d4..2369e16813 100644
--- a/lib/odbc/configure.in
+++ b/lib/odbc/configure.in
@@ -118,11 +118,18 @@ AC_CHECK_FUNC(gethostbyname, , AC_CHECK_LIB(nsl, main, [LIBS="$LIBS -lnsl"]))
dnl Checks for header files.
AC_HEADER_STDC
-AC_CHECK_HEADERS([fcntl.h netdb.h stdlib.h string.h sys/socket.h])
+AC_CHECK_HEADERS([fcntl.h netdb.h stdlib.h string.h sys/socket.h winsock2.h])
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_TYPE_SIZE_T
+AC_CHECK_MEMBERS([struct sockaddr_in6.sin6_addr], [], [],
+ [#if HAVE_WINSOCK2_H
+ #include <winsock2.h>
+ #include <ws2tcpip.h>
+ #else
+ #include <netinet/in.h>
+ #endif])
dnl Checks for library functions.
AC_CHECK_FUNCS([memset socket])
diff --git a/lib/odbc/src/odbc.erl b/lib/odbc/src/odbc.erl
index eb27a471ec..83d9f33102 100644
--- a/lib/odbc/src/odbc.erl
+++ b/lib/odbc/src/odbc.erl
@@ -441,10 +441,12 @@ init(Args) ->
{ok, ListenSocketSup} =
gen_tcp:listen(0, [Inet, binary, {packet, ?LENGTH_INDICATOR_SIZE},
- {active, false}, {nodelay, true}]),
+ {active, false}, {nodelay, true},
+ {ip, loopback}]),
{ok, ListenSocketOdbc} =
gen_tcp:listen(0, [Inet, binary, {packet, ?LENGTH_INDICATOR_SIZE},
- {active, false}, {nodelay, true}]),
+ {active, false}, {nodelay, true},
+ {ip, loopback}]),
%% Start the port program (a c program) that utilizes the odbc driver
case os:find_executable(?SERVERPROG, ?SERVERDIR) of
diff --git a/lib/odbc/vsn.mk b/lib/odbc/vsn.mk
index d813466437..fac3f06d4b 100644
--- a/lib/odbc/vsn.mk
+++ b/lib/odbc/vsn.mk
@@ -1,23 +1 @@
ODBC_VSN = 2.10.8
-
-TICKETS = OTP-7452 OTP-8511
-
-TICKETS_2.10.6 = \
- OTP-8250 \
- OTP-8291
-
-TICKETS_2.10.5 = \
- OTP-7978
-
-TICKETS_2.10.4 = \
- OTP-7720 \
- OTP-7721
-
-TICKETS_2.10.3 = \
- OTP-7418
-TICKETS_2.10.2 = \
- OTP-7297
-TICKETS_2.10.1 = \
- OTP-7019 \
- OTP-7294 \
- OTP-7307
diff --git a/lib/orber/COSS/CosNaming/orber_cosnaming_utils.erl b/lib/orber/COSS/CosNaming/orber_cosnaming_utils.erl
index 7792839e22..768653c898 100644
--- a/lib/orber/COSS/CosNaming/orber_cosnaming_utils.erl
+++ b/lib/orber/COSS/CosNaming/orber_cosnaming_utils.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -536,8 +536,15 @@ lookup(_, _Ctx) ->
receive_msg(Socket, Acc, Timeout) ->
receive
{tcp_closed, Socket} ->
- [_Header, Body] = re:split(Acc,"\r\n\r\n",[{return,list}]),
- Body;
+ case re:split(Acc,"\r\n\r\n",[{return,list}]) of
+ [_Header, Body] ->
+ Body;
+ What ->
+ orber:dbg("[~p] orber_cosnaming_utils:receive_msg();~n"
+ "HTTP server closed the connection before sending a complete reply: ~p.",
+ [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO})
+ end;
{tcp, Socket, Response} ->
receive_msg(Socket, Acc ++ Response, Timeout);
{tcp_error, Socket, Reason} ->
diff --git a/lib/orber/doc/src/notes.xml b/lib/orber/doc/src/notes.xml
index 1013d370e4..6eda16a517 100644
--- a/lib/orber/doc/src/notes.xml
+++ b/lib/orber/doc/src/notes.xml
@@ -33,7 +33,40 @@
</header>
<section>
+ <title>Orber 3.6.18</title>
+ <section>
+ <title>Fixed Bugs and Malfunctions</title>
+ <list type="bulleted">
+ <item>
+ <p>A corbaloc http string could return an EXIT message, instead
+ of a system exception, if the HTTP server closed the socket
+ without returning a complete message. I.e. header and a body
+ containing a stringified IOR.</p>
+ <p>Own Id: OTP-8900 Aux Id: seq11704</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>Orber 3.6.17</title>
+
+ <section>
+ <title>Improvements and New Features</title>
+ <list type="bulleted">
+ <item>
+ <p>
+ Eliminated warnings for auto-imported BIF clashes.</p>
+ <p>
+ Own Id: OTP-8840</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
<title>Orber 3.6.16</title>
+
<section>
<title>Improvements and New Features</title>
<list type="bulleted">
@@ -41,16 +74,17 @@
<p>
Test suites published.</p>
<p>
- Own Id: OTP-8543 Aux Id:</p>
+ Own Id: OTP-8543O Aux Id:</p>
</item>
</list>
</section>
+
<section>
<title>Fixed Bugs and Malfunctions</title>
<list type="bulleted">
<item>
<p>Added missing trailing bracket to define in hrl-file.</p>
- <p>Own id: OTP-8489 Aux Id:</p>
+ <p>Own Id: OTP-8489 Aux Id:</p>
</item>
</list>
</section>
@@ -89,11 +123,11 @@
<list type="bulleted">
<item>
<p>Removed superfluous VT in the documentation.</p>
- <p>Own id: OTP-8353 Aux Id:</p>
+ <p>Own Id: OTP-8353 Aux Id:</p>
</item>
<item>
<p>Removed superfluous backslash in the documentation.</p>
- <p>Own id: OTP-8354 Aux Id:</p>
+ <p>Own Id: OTP-8354 Aux Id:</p>
</item>
</list>
</section>
@@ -125,7 +159,7 @@
<item>
<p>Obsolete guards, e.g. record vs is_record, has been changed
to avoid compiler warnings.</p>
- <p>Own id: OTP-7987</p>
+ <p>Own Id: OTP-7987</p>
</item>
</list>
</section>
@@ -143,7 +177,7 @@
Naming Service (INS) instead. INS is a part of the OMG
standard specification.</p>
<p>*** POTENTIAL INCOMPATIBILITY ***</p>
- <p>Own id: OTP-7906 Aux Id: seq11243</p>
+ <p>Own Id: OTP-7906 Aux Id: seq11243</p>
</item>
</list>
</section>
@@ -157,7 +191,7 @@
<list type="bulleted">
<item>
<p>Updated file headers.</p>
- <p>Own id: OTP-7837</p>
+ <p>Own Id: OTP-7837</p>
</item>
</list>
</section>
@@ -171,7 +205,7 @@
<list type="bulleted">
<item>
<p>Documentation source included in open source releases.</p>
- <p>Own id: OTP-7595</p>
+ <p>Own Id: OTP-7595</p>
</item>
</list>
</section>
@@ -185,11 +219,11 @@
<list type="bulleted">
<item>
<p>Updated file headers.</p>
- <p>Own id: OTP-7011</p>
+ <p>Own Id: OTP-7011</p>
</item>
<item>
<p>Now compliant with the new behavior of stdlib.</p>
- <p>Own id: OTP-7030 Aux Id: seq10827</p>
+ <p>Own Id: OTP-7030 Aux Id: seq10827</p>
</item>
</list>
</section>
diff --git a/lib/orber/src/orber_tb.erl b/lib/orber/src/orber_tb.erl
index 0dd2d95bc8..e6d5ee4400 100644
--- a/lib/orber/src/orber_tb.erl
+++ b/lib/orber/src/orber_tb.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -35,6 +35,8 @@
%%----------------------------------------------------------------------
%% External exports
%%----------------------------------------------------------------------
+%% Avoid warning for local function error/2 clashing with autoimported BIF.
+-compile({no_auto_import,[error/2]}).
-export([wait_for_tables/1, wait_for_tables/2, wait_for_tables/3,
is_loaded/0, is_loaded/1, is_running/0, is_running/1,
info/2, error/2, unique/1, keysearch/2, keysearch/3]).
diff --git a/lib/orber/vsn.mk b/lib/orber/vsn.mk
index ec349ee189..584a52ab84 100644
--- a/lib/orber/vsn.mk
+++ b/lib/orber/vsn.mk
@@ -1,21 +1 @@
-
-ORBER_VSN = 3.6.16
-
-TICKETS = OTP-8489 \
- OTP-8543
-
-TICKETS_3.6.15 = OTP-8353 \
- OTP-8354 \
- OTP-8374 \
- OTP-8409 \
- OTP-8448
-
-TICKETS_3.6.14 = OTP-8201
-
-TICKETS_3.6.13 = OTP-7987
-
-TICKETS_3.6.12 = OTP-7906
-
-TICKETS_3.6.11 = OTP-7837
-
-TICKETS_3.6.10 = OTP-7595
+ORBER_VSN = 3.6.18
diff --git a/lib/os_mon/test/Makefile b/lib/os_mon/test/Makefile
new file mode 100644
index 0000000000..c87285e38b
--- /dev/null
+++ b/lib/os_mon/test/Makefile
@@ -0,0 +1,92 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 1997-2010. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+include $(ERL_TOP)/make/target.mk
+
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+
+MODULES= \
+ os_mon_SUITE \
+ disksup_SUITE \
+ memsup_SUITE \
+ cpu_sup_SUITE \
+ os_mon_mib_SUITE \
+ os_sup_SUITE \
+ os_mon_conf
+
+EBIN = .
+
+HRL_FILES=
+
+ERL_FILES= $(MODULES:%=%.erl)
+
+TARGET_FILES = $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+
+SOURCE = $(ERL_FILES) $(HRL_FILES)
+
+EMAKEFILE=Emakefile
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/os_mon_test
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+ERL_MAKE_FLAGS +=
+ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include \
+ -I$(ERL_TOP)/lib/snmp/include
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+make_emakefile:
+ $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES)\
+ > $(EMAKEFILE)
+
+tests debug opt: make_emakefile
+ erl $(ERL_MAKE_FLAGS) -make
+
+clean:
+ rm -f $(EMAKEFILE)
+ rm -f $(TARGET_FILES)
+ rm -f core *~
+
+docs:
+
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_spec:
+
+release_tests_spec: make_emakefile
+ $(INSTALL_DIR) $(RELSYSDIR)
+ $(INSTALL_DATA) os_mon.spec $(EMAKEFILE) $(SOURCE) $(RELSYSDIR)
+
+## tar chf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+
+release_docs_spec:
diff --git a/lib/os_mon/test/cpu_sup_SUITE.erl b/lib/os_mon/test/cpu_sup_SUITE.erl
new file mode 100644
index 0000000000..45f9d981d1
--- /dev/null
+++ b/lib/os_mon/test/cpu_sup_SUITE.erl
@@ -0,0 +1,282 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(cpu_sup_SUITE).
+-include("test_server.hrl").
+
+%% Test server specific exports
+-export([all/1]).
+-export([init_per_suite/1, end_per_suite/1]).
+-export([init_per_testcase/2, end_per_testcase/2]).
+
+%% Test cases
+-export([load_api/1]).
+-export([util_api/1, util_values/1]).
+-export([port/1]).
+-export([terminate/1, unavailable/1, restart/1]).
+
+%% Default timetrap timeout (set in init_per_testcase)
+-define(default_timeout, ?t:minutes(1)).
+
+init_per_suite(Config) when is_list(Config) ->
+ ?line ok = application:start(os_mon),
+ Config.
+
+end_per_suite(Config) when is_list(Config) ->
+ ?line ok = application:stop(os_mon),
+ Config.
+
+init_per_testcase(_Case, Config) ->
+ Dog = ?t:timetrap(?default_timeout),
+ [{watchdog, Dog} | Config].
+
+end_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+all(suite) ->
+ case ?t:os_type() of
+ {unix, sunos} ->
+ [load_api, util_api, util_values, port,
+ {conf, terminate, [unavailable], restart}];
+ {unix, linux} ->
+ [load_api, util_api, util_values, port,
+ {conf, terminate, [unavailable], restart}];
+ {unix, _OSname} ->
+ [load_api];
+ _OS ->
+ [unavailable]
+ end.
+
+load_api(suite) ->
+ [];
+load_api(doc) ->
+ ["Test of load API functions"];
+load_api(Config) when is_list(Config) ->
+
+ %% nprocs()
+ ?line N = cpu_sup:nprocs(),
+ ?line true = is_integer(N),
+ ?line true = N>0,
+
+ %% avg1()
+ ?line Load1 = cpu_sup:avg1(),
+ ?line true = is_integer(Load1),
+ ?line true = Load1>0,
+
+ %% avg5()
+ ?line Load5 = cpu_sup:avg5(),
+ ?line true = is_integer(Load5),
+ ?line true = Load5>0,
+
+ %% avg15()
+ ?line Load15 = cpu_sup:avg15(),
+ ?line true = is_integer(Load15),
+ ?line true = Load15>0,
+
+ ok.
+
+util_api(suite) ->
+ [];
+util_api(doc) ->
+ ["Test of utilization API functions"];
+util_api(Config) when is_list(Config) ->
+ %% Some useful funs when testing util/1
+ BusyP = fun({user, _Share}) -> true;
+ ({nice_user, _Share}) -> true;
+ ({kernel, _Share}) -> true;
+ ({hard_irq, _Share}) -> true;
+ ({soft_irq, _Share}) -> true;
+ (_) -> false
+ end,
+ NonBusyP = fun({wait, _Share}) -> true;
+ ({idle, _Share}) -> true;
+ ({steal, _Share}) -> true;
+ (_) -> false
+ end,
+ Sum = fun({_Tag, X}, Acc) -> Acc+X end,
+
+ %% util()
+ ?line Util1 = cpu_sup:util(),
+ ?line true = is_number(Util1),
+ ?line true = Util1>0,
+ ?line Util2 = cpu_sup:util(),
+ ?line true = is_number(Util2),
+ ?line true = Util2>0,
+
+ %% util([])
+ ?line {all, Busy1, NonBusy1, []} = cpu_sup:util([]),
+ ?line 100.00 = Busy1 + NonBusy1,
+
+ %% util([detailed])
+ ?line {Cpus2, Busy2, NonBusy2, []} = cpu_sup:util([detailed]),
+ ?line true = lists:all(fun(X) -> is_integer(X) end, Cpus2),
+ ?line true = lists:all(BusyP, Busy2),
+ ?line true = lists:all(NonBusyP, NonBusy2),
+ ?line 100.00 = lists:foldl(Sum,0,Busy2)+lists:foldl(Sum,0,NonBusy2),
+
+ %% util([per_cpu])
+ ?line [{Cpu3, Busy3, NonBusy3, []}|_] = cpu_sup:util([per_cpu]),
+ ?line true = is_integer(Cpu3),
+ ?line 100.00 = Busy3 + NonBusy3,
+
+ %% util([detailed, per_cpu])
+ ?line [{Cpu4, Busy4, NonBusy4, []}|_] =
+ cpu_sup:util([detailed, per_cpu]),
+ ?line true = is_integer(Cpu4),
+ ?line true = lists:all(BusyP, Busy2),
+ ?line true = lists:all(NonBusyP, NonBusy2),
+ ?line 100.00 = lists:foldl(Sum,0,Busy4)+lists:foldl(Sum,0,NonBusy4),
+
+ %% bad util/1 calls
+ ?line {'EXIT',{badarg,_}} = (catch cpu_sup:util(detailed)),
+ ?line {'EXIT',{badarg,_}} = (catch cpu_sup:util([detialed])),
+
+ ok.
+
+-define(SPIN_TIME, 1000).
+
+util_values(suite) ->
+ [];
+util_values(doc) ->
+ ["Test utilization values"];
+util_values(Config) when is_list(Config) ->
+
+ Tester = self(),
+ Ref = make_ref(),
+ Loop = fun (L) -> L(L) end,
+ Spinner = fun () ->
+ Looper = spawn_link(fun () -> Loop(Loop) end),
+ receive after ?SPIN_TIME -> ok end,
+ unlink(Looper),
+ exit(Looper, kill),
+ Tester ! Ref
+ end,
+
+ ?line cpu_sup:util(),
+
+ ?line spawn_link(Spinner),
+ ?line receive Ref -> ok end,
+ ?line HighUtil1 = cpu_sup:util(),
+
+ ?line receive after ?SPIN_TIME -> ok end,
+ ?line LowUtil1 = cpu_sup:util(),
+
+ ?line spawn_link(Spinner),
+ ?line receive Ref -> ok end,
+ ?line HighUtil2 = cpu_sup:util(),
+
+ ?line receive after ?SPIN_TIME -> ok end,
+ ?line LowUtil2 = cpu_sup:util(),
+
+ Utils = [{high1,HighUtil1}, {low1,LowUtil1},
+ {high2,HighUtil2}, {low2,LowUtil2}],
+ ?t:format("Utils: ~p~n", [Utils]),
+
+ ?line false = LowUtil1 > HighUtil1,
+ ?line false = LowUtil1 > HighUtil2,
+ ?line false = LowUtil2 > HighUtil1,
+ ?line false = LowUtil2 > HighUtil2,
+
+ ok.
+
+
+% Outdated
+% The portprogram is now restarted if killed, and not by os_mon...
+
+port(suite) ->
+ [];
+port(doc) ->
+ ["Test that cpu_sup handles a terminating port program"];
+port(Config) when is_list(Config) ->
+ case cpu_sup_os_pid() of
+ {ok, PidStr} ->
+ %% Monitor cpu_sup
+ ?line MonRef = erlang:monitor(process, cpu_sup),
+ ?line N1 = cpu_sup:nprocs(),
+ ?line true = N1>0,
+
+ %% Kill the port program
+ case os:cmd("kill -9 " ++ PidStr) of
+ [] ->
+ %% cpu_sup should not terminate
+ receive
+ {'DOWN', MonRef, _, _, Reason} ->
+ ?line ?t:fail({unexpected_exit_reason, Reason})
+ after 3000 ->
+ ok
+ end,
+
+ %% Give cpu_sup time to restart cpu_sup port
+ ?t:sleep(?t:seconds(3)),
+ ?line N2 = cpu_sup:nprocs(),
+ ?line true = N2>0,
+
+ erlang:demonitor(MonRef),
+ ok;
+
+ Line ->
+ erlang:demonitor(MonRef),
+ {skip, {not_killed, Line}}
+ end;
+ _ ->
+ {skip, os_pid_not_found }
+ end.
+
+terminate(suite) ->
+ [];
+terminate(Config) when is_list(Config) ->
+ ?line ok = application:set_env(os_mon, start_cpu_sup, false),
+ ?line ok = supervisor:terminate_child(os_mon_sup, cpu_sup),
+ ok.
+
+unavailable(suite) ->
+ [];
+unavailable(doc) ->
+ ["Test correct behaviour when service is unavailable"];
+unavailable(Config) when is_list(Config) ->
+
+ %% Make sure all API functions return their dummy values
+ ?line 0 = cpu_sup:nprocs(),
+ ?line 0 = cpu_sup:avg1(),
+ ?line 0 = cpu_sup:avg5(),
+ ?line 0 = cpu_sup:avg15(),
+ ?line 0 = cpu_sup:util(),
+ ?line {all,0,0,[]} = cpu_sup:util([]),
+ ?line {all,0,0,[]} = cpu_sup:util([detailed]),
+ ?line {all,0,0,[]} = cpu_sup:util([per_cpu]),
+ ?line {all,0,0,[]} = cpu_sup:util([detailed,per_cpu]),
+
+ ok.
+
+restart(suite) ->
+ [];
+restart(Config) when is_list(Config) ->
+ ?line ok = application:set_env(os_mon, start_cpu_sup, true),
+ ?line {ok, _Pid} = supervisor:restart_child(os_mon_sup, cpu_sup),
+ ok.
+
+%% Aux
+
+cpu_sup_os_pid() ->
+ Str = os:cmd("ps -e | grep '[c]pu_sup'"),
+ case io_lib:fread("~s", Str) of
+ {ok, [Pid], _Rest} -> {ok, Pid};
+ _ -> {error, pid_not_found}
+ end.
diff --git a/lib/os_mon/test/disksup_SUITE.erl b/lib/os_mon/test/disksup_SUITE.erl
new file mode 100644
index 0000000000..987d631c36
--- /dev/null
+++ b/lib/os_mon/test/disksup_SUITE.erl
@@ -0,0 +1,426 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(disksup_SUITE).
+-include("test_server.hrl").
+
+%% Test server specific exports
+-export([all/1]).
+-export([init_per_suite/1, end_per_suite/1]).
+-export([init_per_testcase/2, end_per_testcase/2]).
+
+%% Test cases
+-export([api/1, config/1, alarm/1]).
+-export([port/1]).
+-export([terminate/1, unavailable/1, restart/1]).
+-export([otp_5910/1]).
+
+%% Default timetrap timeout (set in init_per_testcase)
+-define(default_timeout, ?t:minutes(1)).
+
+init_per_suite(Config) when is_list(Config) ->
+ ?line ok = application:start(os_mon),
+ Config.
+
+end_per_suite(Config) when is_list(Config) ->
+ ?line ok = application:stop(os_mon),
+ Config.
+
+init_per_testcase(_Case, Config) ->
+ Dog = ?t:timetrap(?default_timeout),
+ [{watchdog,Dog} | Config].
+
+end_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+all(suite) ->
+ Bugs = [otp_5910],
+ case ?t:os_type() of
+ {unix, sunos} ->
+ [api, config, alarm, port,
+ {conf, terminate, [unavailable], restart}] ++ Bugs;
+ {unix, _OSname} ->
+ [api, alarm] ++ Bugs;
+ {win32, _OSname} ->
+ [api, alarm] ++ Bugs;
+ _OS ->
+ [unavailable]
+ end.
+
+api(suite) ->
+ [];
+api(doc) ->
+ ["Test of API functions"];
+api(Config) when is_list(Config) ->
+
+ %% get_disk_data()
+ ?line [{Id, KByte, Capacity}|_] = disksup:get_disk_data(),
+ ?line true = io_lib:printable_list(Id),
+ ?line true = is_integer(KByte),
+ ?line true = is_integer(Capacity),
+ ?line true = KByte>0,
+ ?line true = Capacity>0,
+
+ %% get_check_interval()
+ ?line 1800000 = disksup:get_check_interval(),
+
+ %% set_check_interval(Minutes)
+ ?line ok = disksup:set_check_interval(20),
+ ?line 1200000 = disksup:get_check_interval(),
+ ?line {'EXIT',{badarg,_}} = (catch disksup:set_check_interval(0.5)),
+ ?line 1200000 = disksup:get_check_interval(),
+ ?line ok = disksup:set_check_interval(30),
+
+ %% get_almost_full_threshold()
+ ?line 80 = disksup:get_almost_full_threshold(),
+
+ %% set_almost_full_threshold(Float)
+ ?line ok = disksup:set_almost_full_threshold(0.90),
+ ?line 90 = disksup:get_almost_full_threshold(),
+ ?line {'EXIT',{badarg,_}} =
+ (catch disksup:set_almost_full_threshold(-0.5)),
+ ?line 90 = disksup:get_almost_full_threshold(),
+ ?line ok = disksup:set_almost_full_threshold(0.80),
+
+ ok.
+
+config(suite) ->
+ [];
+config(doc) ->
+ ["Test configuration"];
+config(Config) when is_list(Config) ->
+
+ %% Change configuration parameters and make sure change is reflected
+ %% when disksup is restarted
+ ?line ok =
+ application:set_env(os_mon, disk_space_check_interval, 29),
+ ?line ok =
+ application:set_env(os_mon, disk_almost_full_threshold, 0.81),
+
+ ?line ok = supervisor:terminate_child(os_mon_sup, disksup),
+ ?line {ok, _Child1} = supervisor:restart_child(os_mon_sup, disksup),
+
+ ?line 1740000 = disksup:get_check_interval(),
+ ?line 81 = disksup:get_almost_full_threshold(),
+
+ %% Also try this with bad parameter values, should be ignored
+ ?line ok =
+ application:set_env(os_mon, disk_space_check_interval, 0.5),
+ ?line ok =
+ application:set_env(os_mon, disk_almost_full_threshold, -0.81),
+
+ ?line ok = supervisor:terminate_child(os_mon_sup, disksup),
+ ?line {ok, _Child2} = supervisor:restart_child(os_mon_sup, disksup),
+
+ ?line 1800000 = disksup:get_check_interval(),
+ ?line 80 = disksup:get_almost_full_threshold(),
+
+ %% Reset configuration parameters
+ ?line ok =
+ application:set_env(os_mon, disk_space_check_interval, 30),
+ ?line ok =
+ application:set_env(os_mon, disk_almost_full_threshold, 0.80),
+
+ ok.
+
+%%----------------------------------------------------------------------
+%% NOTE: The test case is a bit weak as it will fail if the disk usage
+%% changes too much during its course, or if there are timing problems
+%% with the alarm_handler receiving the alarms too late
+%%----------------------------------------------------------------------
+alarm(suite) ->
+ [];
+alarm(doc) ->
+ ["Test that alarms are set and cleared"];
+alarm(Config) when is_list(Config) ->
+
+ %% Find out how many disks exceed the threshold
+ %% and make sure the corresponding number of alarms is set
+ ?line Threshold1 = disksup:get_almost_full_threshold(), % 80
+ ?line Data1 = disksup:get_disk_data(),
+ ?line Over1 = over_threshold(Data1, Threshold1),
+ ?line Alarms1 = get_alarms(),
+ if
+ Over1==length(Alarms1) ->
+ ?line true;
+ true ->
+ dump_info(),
+ ?line ?t:fail({bad_alarms, Threshold1, Data1, Alarms1})
+ end,
+
+ %% Try to find a disk with space usage below Threshold1,
+ %% lower the threshold accordingly and make sure new alarms are set
+ Fun1 = fun({_Id, _Kbyte, Capacity}) ->
+ if
+ Capacity>0, Capacity<Threshold1 -> true;
+ true -> false
+ end
+ end,
+ ?line case until(Fun1, Data1) of
+ {_, _, Cap1} ->
+ Threshold2 = Cap1-1,
+ ?line ok =
+ disksup:set_almost_full_threshold(Threshold2/100),
+ ?line disksup ! timeout, % force a disk check
+ ?line Data2 = disksup:get_disk_data(),
+ ?line Over2 = over_threshold(Data2, Threshold2),
+ ?line Alarms2 = get_alarms(),
+ if
+ Over2==length(Alarms2), Over2>Over1 ->
+ ?line true;
+ true ->
+ dump_info(),
+ ?line ?t:fail({bad_alarms, Threshold2, Data2, Alarms2})
+ end;
+ false ->
+ ?line ignore
+ end,
+
+ %% Find out the highest space usage among all disks
+ %% and try to raise the threshold above this value,
+ %% make sure all alarms are cleared
+ Fun2 = fun({_Id, _Kbyte, Capacity}, MaxAcc) ->
+ if
+ Capacity>MaxAcc -> Capacity;
+ true -> MaxAcc
+ end
+ end,
+ ?line case lists:foldl(Fun2, 0, Data1) of
+ Max when Max<100 ->
+ Threshold3 = Max+1,
+ ?line ok =
+ disksup:set_almost_full_threshold(Threshold3/100),
+ ?line disksup ! timeout, % force a disk check
+ ?line Data3 = disksup:get_disk_data(),
+ ?line Over3 = over_threshold(Data3, Threshold3),
+ ?line Alarms3 = get_alarms(),
+ if
+ Over3==0, length(Alarms3)==0 ->
+ ?line ok;
+ true ->
+ dump_info(),
+ ?line ?t:fail({bad_alarms, Threshold3, Data3, Alarms3})
+ end;
+ 100 ->
+ ?line ignore
+ end,
+
+ %% Reset threshold
+ ?line ok = disksup:set_almost_full_threshold(Threshold1/100),
+
+ ok.
+
+over_threshold(Data, Threshold) ->
+ Data2 = remove_duplicated_disks(lists:keysort(1, Data)),
+ lists:foldl(fun({_Id, _Kbyte, Cap}, N) when Cap>=Threshold ->
+ N+1;
+ (_DiskData, N) ->
+ N
+ end,
+ 0,
+ Data2).
+
+%% On some platforms (for example MontaVista) data for one disk can be
+%% "duplicated":
+%% Linux ppb 2.4.20_mvl31-pcore680 #1 Sun Feb 1 23:12:56 PST 2004 ppc unknown
+%%
+%% MontaVista(R) Linux(R) Professional Edition 3.1
+%%
+%% [ppb:~]> /bin/df -lk
+%% Filesystem 1k-blocks Used Available Use% Mounted on
+%% rootfs 8066141 3023763 4961717 38% /
+%% /dev/root 8066141 3023763 4961717 38% /
+%% tmpfs 192892 0 192892 0% /dev/shm
+%%
+%% disksup:
+%% [{"/",8066141,38}, {"/",8066141,38}, {"/dev/shm",192892,0}]
+%%
+%% disksup will only set ONE alarm for "/".
+%% Therefore the list of disk data must be sorted and duplicated disk
+%% tuples removed before calculating how many alarms should be set, or
+%% the testcase will fail erroneously.
+remove_duplicated_disks([{Id, _, _}, {Id, Kbyte, Cap}|T]) ->
+ remove_duplicated_disks([{Id, Kbyte, Cap}|T]);
+remove_duplicated_disks([H|T]) ->
+ [H|remove_duplicated_disks(T)];
+remove_duplicated_disks([]) ->
+ [].
+
+get_alarms() ->
+ lists:filter(fun({{disk_almost_full, _Disk},_}) -> true;
+ (_) -> false
+ end,
+ alarm_handler:get_alarms()).
+
+until(Fun, [H|T]) ->
+ case Fun(H) of
+ true -> H;
+ false ->
+ until(Fun, T)
+ end;
+until(_Fun, []) ->
+ false.
+
+port(suite) ->
+ [];
+port(doc) ->
+ ["Test that disksup handles a terminating port program"];
+port(Config) when is_list(Config) ->
+ ?line Str = os:cmd("ps -ef | grep '[d]isksup'"),
+ case io_lib:fread("~s ~s", Str) of
+ {ok, [_Uid,Pid], _Rest} ->
+
+ %% Monitor disksup
+ ?line MonRef = erlang:monitor(process, disksup),
+ ?line [{_Disk1,Kbyte1,_Cap1}|_] = disksup:get_disk_data(),
+ ?line true = Kbyte1>0,
+
+ %% Kill the port program
+ case os:cmd("kill -9 " ++ Pid) of
+ [] ->
+
+ %% disksup should now terminate
+ receive
+ {'DOWN', MonRef, _, _, {port_died, _Reason}} ->
+ ok;
+ {'DOWN', MonRef, _, _, Reason} ->
+ ?line ?t:fail({unexpected_exit_reason, Reason})
+ after
+ 3000 ->
+ ?line ?t:fail({still_alive, Str})
+ end,
+
+ %% Give os_mon_sup time to restart disksup
+ ?t:sleep(?t:seconds(3)),
+ ?line [{_Disk2,Kbyte2,_Cap2}|_] =
+ disksup:get_disk_data(),
+ ?line true = Kbyte2>0,
+
+ ok;
+
+ Line ->
+ erlang:demonitor(MonRef),
+ {skip, {not_killed, Line}}
+ end;
+ _ ->
+ {skip, {os_pid_not_found, Str}}
+ end.
+
+terminate(suite) ->
+ [];
+terminate(Config) when is_list(Config) ->
+ ?line ok = application:set_env(os_mon, start_disksup, false),
+ ?line ok = supervisor:terminate_child(os_mon_sup, disksup),
+ ok.
+
+unavailable(suite) ->
+ [];
+unavailable(doc) ->
+ ["Test correct behaviour when service is unavailable"];
+unavailable(Config) when is_list(Config) ->
+
+ %% Make sure all API functions return their dummy values
+ ?line [{"none",0,0}] = disksup:get_disk_data(),
+ ?line 1800000 = disksup:get_check_interval(),
+ ?line ok = disksup:set_check_interval(5),
+ ?line 80 = disksup:get_almost_full_threshold(),
+ ?line ok = disksup:set_almost_full_threshold(0.9),
+
+ ok.
+
+restart(suite) ->
+ [];
+restart(Config) when is_list(Config) ->
+ ?line ok = application:set_env(os_mon, start_disksup, true),
+ ?line {ok, _Pid} = supervisor:restart_child(os_mon_sup, disksup),
+ ok.
+
+otp_5910(suite) ->
+ [];
+otp_5910(doc) ->
+ ["Test that alarms are cleared if disksup crashes or "
+ "if OS_Mon is stopped"];
+otp_5910(Config) when is_list(Config) ->
+
+ %% Make sure disksup sets at least one alarm
+ ?line Data = disksup:get_disk_data(),
+ ?line Threshold0 = disksup:get_almost_full_threshold(),
+ ?line Threshold = case over_threshold(Data, Threshold0) of
+ 0 ->
+ [{_Id,_Kbyte,Cap}|_] = Data,
+ ?line ok = disksup:set_almost_full_threshold((Cap-1)/100),
+ Cap-1;
+ _N ->
+ Threshold0
+ end,
+ ?line ok = application:set_env(os_mon,
+ disk_almost_full_threshold,
+ Threshold/100),
+ ?line disksup ! timeout, % force a disk check
+ ?line Data2 = disksup:get_disk_data(),
+ ?line Over = over_threshold(Data2, Threshold),
+ ?line Alarms = get_alarms(),
+ if
+ Over==0 ->
+ ?line ?t:fail({threshold_too_low, Data2, Threshold});
+ Over==length(Alarms) ->
+ ok;
+ true ->
+ dump_info(),
+ ?line ?t:fail({bad_alarms, Threshold, Data2, Alarms})
+ end,
+
+ %% Kill disksup
+ exit(whereis(disksup), faked_disksup_crash),
+
+ %% Wait a little to make sure disksup has been restarted,
+ %% then make sure the alarms are set once, but not twice
+ ?t:sleep(?t:seconds(1)),
+ ?line Data3 = disksup:get_disk_data(),
+ ?line Alarms2 = get_alarms(),
+ if
+ length(Alarms2)==length(Alarms) ->
+ ok;
+ true ->
+ dump_info(),
+ ?line ?t:fail({bad_alarms, Threshold, Data3, Alarms,Alarms2})
+ end,
+
+ %% Stop OS_Mon and make sure all disksup alarms are cleared
+ ?line ok = application:stop(os_mon),
+ ?t:sleep(?t:seconds(1)),
+ ?line Alarms3 = get_alarms(),
+ if
+ length(Alarms3)==0 ->
+ ok;
+ true ->
+ ?line ?t:fail({alarms_not_cleared, Alarms3})
+ end,
+
+ %% Reset threshold and restart OS_Mon
+ ?line ok = application:set_env(os_mon,
+ disksup_almost_full_threshold, 0.8),
+ ?line ok = disksup:set_almost_full_threshold(0.8),
+ ?line ok = application:start(os_mon),
+
+ ok.
+
+dump_info() ->
+ io:format("Status: ~p~n", [sys:get_status(disksup)]).
diff --git a/lib/os_mon/test/memsup_SUITE.erl b/lib/os_mon/test/memsup_SUITE.erl
new file mode 100644
index 0000000000..01a7f6c7f2
--- /dev/null
+++ b/lib/os_mon/test/memsup_SUITE.erl
@@ -0,0 +1,782 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(memsup_SUITE).
+-include("test_server.hrl").
+
+%% Test server specific exports
+-export([all/1]).
+-export([init_per_suite/1, end_per_suite/1]).
+-export([init_per_testcase/2, end_per_testcase/2]).
+
+%% Test cases
+-export([api/1, alarm1/1, alarm2/1, process/1]).
+-export([config/1, timeout/1, unavailable/1, port/1]).
+-export([otp_5910/1]).
+
+%% Default timetrap timeout (set in init_per_testcase)
+-define(default_timeout, ?t:minutes(1)).
+
+init_per_suite(Config) when is_list(Config) ->
+ ?line ok = application:start(os_mon),
+ Config.
+
+end_per_suite(Config) when is_list(Config) ->
+ ?line ok = application:stop(os_mon),
+ Config.
+
+init_per_testcase(_Case, Config) ->
+ Dog = ?t:timetrap(?default_timeout),
+ [{watchdog,Dog} | Config].
+
+end_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ Config.
+
+all(suite) ->
+ All = case ?t:os_type() of
+ {unix, sunos} ->
+ [api, alarm1, alarm2, process,
+ config, timeout, unavailable, port];
+ {unix, linux} ->
+ [api, alarm1, alarm2, process, timeout];
+ _OS ->
+ [api, alarm1, alarm2, process]
+ end,
+ Bugs = [otp_5910],
+ All ++ Bugs.
+
+api(suite) ->
+ [];
+api(doc) ->
+ ["Test of API functions"];
+api(Config) when is_list(Config) ->
+
+ %% get_memory_data()
+ ?line RegMemData = memsup:get_memory_data(),
+ case RegMemData of
+ {TotMem, AllBytes, {Pid, PidBytes}} when is_integer(TotMem),
+ is_integer(AllBytes),
+ is_pid(Pid),
+ is_integer(PidBytes) ->
+ ok;
+ {0, 0, _WorstPid} ->
+ ?line ?t:fail(first_data_collection_failed);
+ _ ->
+ ?line ?t:fail({bad_return, RegMemData})
+ end,
+
+ %% get_system_memory_data()
+ ?line ExtMemData = memsup:get_system_memory_data(),
+ Tags = [ total_memory,
+ free_memory,
+ system_total_memory,
+ largest_free,
+ number_of_free,
+ free_swap,
+ total_swap,
+ cached_memory,
+ buffered_memory,
+ shared_memory],
+
+ ?line true = lists:all(fun({Tag,Value}) when is_atom(Tag),
+ is_integer(Value) ->
+ lists:member(Tag, Tags);
+ (_) ->
+ false
+ end,
+ ExtMemData),
+
+ %% get_os_wordsize()
+ ?line ok = case memsup:get_os_wordsize() of
+ 32 -> ok;
+ 64 -> ok;
+ unsupported_os -> ok;
+ _ -> error
+ end,
+
+ %% get_check_interval()
+ ?line 60000 = memsup:get_check_interval(),
+
+ %% set_check_interval(Minutes)
+ ?line ok = memsup:set_check_interval(2),
+ ?line 120000 = memsup:get_check_interval(),
+ ?line {'EXIT',{badarg,_}} =
+ (catch memsup:set_check_interval(0.2)),
+ ?line 120000 = memsup:get_check_interval(),
+ ?line ok = memsup:set_check_interval(1),
+
+ %% get_procmem_high_watermark()
+ ?line 5 = memsup:get_procmem_high_watermark(),
+
+ %% set_procmem_high_watermark()
+ ?line ok = memsup:set_procmem_high_watermark(0.1),
+ ?line 10 = memsup:get_procmem_high_watermark(),
+ ?line {'EXIT',{badarg,_}} =
+ (catch memsup:set_procmem_high_watermark(-0.1)),
+ ?line 10 = memsup:get_procmem_high_watermark(),
+ ?line ok = memsup:set_procmem_high_watermark(0.05),
+
+ %% get_sysmem_high_watermark()
+ ?line 80 = memsup:get_sysmem_high_watermark(),
+
+ %% set_sysmem_high_watermark()
+ ?line ok = memsup:set_sysmem_high_watermark(0.9),
+ ?line 90 = memsup:get_sysmem_high_watermark(),
+ ?line {'EXIT',{badarg,_}} =
+ (catch memsup:set_sysmem_high_watermark(-0.9)),
+ ?line 90 = memsup:get_sysmem_high_watermark(),
+ ?line ok = memsup:set_sysmem_high_watermark(0.8),
+
+ %% get|set_helper_timeout
+ ?line 30 = memsup:get_helper_timeout(),
+ ?line ok = memsup:set_helper_timeout(29),
+ ?line 29 = memsup:get_helper_timeout(),
+ ?line {'EXIT',{badarg,_}} = (catch memsup:set_helper_timeout(31.0)),
+ ?line 29 = memsup:get_helper_timeout(),
+ ok.
+
+%%----------------------------------------------------------------------
+%% NOTE: The test case is a bit weak as it will fail if the memory
+%% usage changes too much during its course.
+%%----------------------------------------------------------------------
+alarm1(suite) ->
+ [];
+alarm1(doc) ->
+ ["Test alarms when memsup_system_only==false"];
+alarm1(Config) when is_list(Config) ->
+
+ %% If system memory usage is too high, the testcase cannot
+ %% be run correctly
+ ?line {Total, Alloc, {_Pid,_PidAlloc}} = memsup:get_memory_data(),
+ io:format("alarm1: Total: ~p, Alloc: ~p~n", [Total, Alloc]),
+ ?line SysUsage = Alloc/Total,
+ if
+ SysUsage>0.99 ->
+ {skip, sys_mem_too_high};
+ true ->
+ alarm1(Config, SysUsage)
+ end.
+
+alarm1(_Config, SysUsage) ->
+ %% Set a long memory check interval, we will force memory checks
+ %% instead
+ ?line ok = memsup:set_check_interval(60),
+
+ %% Check thresholds
+ ?line SysThreshold = (memsup:get_sysmem_high_watermark()/100),
+ ?line ProcThreshold = (memsup:get_procmem_high_watermark()/100),
+
+ %% Check if a system alarm already should be set or not
+ SysP = if
+ SysUsage>SysThreshold -> true;
+ SysUsage=<SysThreshold -> false
+ end,
+
+ %% If system memory is higher than threshold, make sure the system
+ %% alarm is set. Otherwise, make sure it is not set
+ case alarm_set(system_memory_high_watermark) of
+ {true, []} when SysP ->
+ ok;
+ false when not SysP ->
+ ok;
+ _ ->
+ ?line ?t:fail({sys_alarm, SysUsage, SysThreshold})
+ end,
+
+ %% Lower/raise the threshold to clear/set the alarm
+ NewSysThreshold = if
+ SysP ->
+ Value = 1.1*SysUsage,
+ if
+ Value > 0.99 -> 0.99;
+ true -> Value
+ end;
+ not SysP -> 0.9*SysUsage
+ end,
+
+ ?line ok = memsup:set_sysmem_high_watermark(NewSysThreshold),
+
+ %% Initiate and wait for a new data collection
+ ?line ok = force_collection(),
+
+ %% Make sure the alarm is cleared/set
+ ?t:sleep(?t:seconds(5)),
+ case alarm_set(system_memory_high_watermark) of
+ {true, []} when not SysP ->
+ ok;
+ false when SysP ->
+ ok;
+ _ ->
+ ?line ?t:fail({sys_alarm, SysUsage, NewSysThreshold})
+ end,
+
+ %% Reset the threshold to set/clear the alarm again
+ ?line ok = memsup:set_sysmem_high_watermark(SysThreshold),
+ ?line ok = force_collection(),
+ ?t:sleep(?t:seconds(1)),
+ case alarm_set(system_memory_high_watermark) of
+ {true, []} when SysP ->
+ ok;
+ false when not SysP ->
+ ok;
+ _ ->
+ ?line ?t:fail({sys_alarm, SysUsage, SysThreshold})
+ end,
+
+ %% Check memory usage
+ ?line {Total2, _, {WorstPid, PidAlloc}} = memsup:get_memory_data(),
+
+ %% Check if a process alarm already should be set or not
+ PidUsage = PidAlloc/Total2,
+ ProcP = if
+ PidUsage>ProcThreshold -> true;
+ PidUsage=<ProcThreshold -> false
+ end,
+
+ %% Make sure the process alarm is set/not set accordingly
+ case alarm_set(process_memory_high_watermark) of
+ {true, WorstPid} when ProcP ->
+ ok;
+ false when not ProcP ->
+ ok;
+ {true, BadPid1} when ProcP ->
+ ?line ?t:fail({proc_alarm, WorstPid, BadPid1});
+ _ ->
+ ?line ?t:fail({proc_alarm, PidUsage, ProcThreshold})
+ end,
+
+ %% Lower/raise the threshold to clear/set the alarm
+ NewProcThreshold = if
+ ProcP -> 1.1*PidUsage;
+ not ProcP -> 0.9*PidUsage
+ end,
+ ?line ok = memsup:set_procmem_high_watermark(NewProcThreshold),
+ ?line ok = force_collection(),
+ ?t:sleep(?t:seconds(1)),
+ case alarm_set(process_memory_high_watermark) of
+ {true, WorstPid} when not ProcP ->
+ ok;
+ false when ProcP ->
+ ok;
+ {true, BadPid2} when not ProcP ->
+ ?line test_server:fail({proc_alarm, WorstPid, BadPid2});
+ _ ->
+ ?line ?t:fail({proc_alarm, PidUsage, ProcThreshold})
+ end,
+
+ %% Reset the threshold to clear/set the alarm
+ ?line ok = memsup:set_procmem_high_watermark(ProcThreshold),
+ ?line ok = force_collection(),
+ ?t:sleep(?t:seconds(1)),
+ case alarm_set(process_memory_high_watermark) of
+ {true, WorstPid} when ProcP ->
+ ok;
+ false when not ProcP ->
+ ok;
+ {true, BadPid3} when ProcP ->
+ ?line test_server:fail({proc_alarm, WorstPid, BadPid3});
+ _ ->
+ ?line ?t:fail({proc_alarm, PidUsage, ProcThreshold})
+ end,
+
+ %% Reset memory check interval
+ ?line ok = memsup:set_check_interval(1),
+ ok.
+
+alarm2(suite) ->
+ [];
+alarm2(doc) ->
+ ["Test alarms when memsup_system_only==true"];
+alarm2(Config) when is_list(Config) ->
+
+ %% If system memory usage is too high, the testcase cannot
+ %% be run correctly
+ ?line {Total, Alloc, {_Pid,_PidAlloc}} = memsup:get_memory_data(),
+ ?line SysUsage = Alloc/Total,
+ if
+ SysUsage>0.99 ->
+ {skip, sys_mem_too_high};
+ true ->
+ alarm2(Config, SysUsage)
+ end.
+
+alarm2(_Config, _SysUsage) ->
+
+ %% Change memsup_system_only and restart memsup
+ ?line ok = application:set_env(os_mon, memsup_system_only, true),
+ ?line ok = supervisor:terminate_child(os_mon_sup, memsup),
+ ?line {ok, _Memsup1} = supervisor:restart_child(os_mon_sup, memsup),
+
+ %% Set a long memory check interval, we will force memory checks
+ %% instead
+ ?line ok = memsup:set_check_interval(60),
+
+ %% Check data and thresholds
+ ?line {Total, Alloc, undefined} = memsup:get_memory_data(),
+ ?line SysThreshold = (memsup:get_sysmem_high_watermark()/100),
+ ?line true = is_integer(memsup:get_procmem_high_watermark()),
+
+ %% Check if a system alarm already should be set or not
+ ?line SysUsage = Alloc/Total,
+ SysP = if
+ SysUsage>SysThreshold -> true;
+ SysUsage=<SysThreshold -> false
+ end,
+
+ %% If system memory is higher than threshold, make sure the system
+ %% alarm is set. Otherwise, make sure it is not set
+ case alarm_set(system_memory_high_watermark) of
+ {true, []} when SysP ->
+ ok;
+ false when not SysP ->
+ ok;
+ _ ->
+ ?line ?t:fail({sys_alarm, SysUsage, SysThreshold})
+ end,
+
+ %% Lower/raise the threshold to clear/set the alarm
+ NewSysThreshold = if
+ SysP ->
+ Value = 1.1*SysUsage,
+ if
+ Value > 0.99 -> 0.99;
+ true -> Value
+ end;
+ not SysP -> 0.9*SysUsage
+ end,
+
+ ?line ok = memsup:set_sysmem_high_watermark(NewSysThreshold),
+
+ %% Initiate and wait for a new data collection
+ ?line ok = force_collection(),
+
+ %% Make sure the alarm is cleared/set
+ ?t:sleep(?t:seconds(1)),
+ case alarm_set(system_memory_high_watermark) of
+ {true, []} when not SysP ->
+ ok;
+ false when SysP ->
+ ok;
+ _ ->
+ ?line ?t:fail({sys_alarm, SysUsage, NewSysThreshold})
+ end,
+
+ %% Reset the threshold to set/clear the alarm again
+ ?line ok = memsup:set_sysmem_high_watermark(SysThreshold),
+ ?line ok = force_collection(),
+ ?t:sleep(?t:seconds(1)),
+ case alarm_set(system_memory_high_watermark) of
+ {true, []} when SysP ->
+ ok;
+ false when not SysP ->
+ ok;
+ _ ->
+ ?line ?t:fail({sys_alarm, SysUsage, SysThreshold})
+ end,
+
+ %% Reset memsup_system_only and restart memsup
+ %% (memory check interval is then automatically reset)
+ ?line ok = application:set_env(os_mon, memsup_system_only, false),
+ ?line ok = supervisor:terminate_child(os_mon_sup, memsup),
+ ?line {ok, _Memsup2} = supervisor:restart_child(os_mon_sup, memsup),
+
+ ok.
+
+alarm_set(Alarm) ->
+ alarm_set(Alarm, alarm_handler:get_alarms()).
+alarm_set(Alarm, [{Alarm,Data}|_]) ->
+ {true,Data};
+alarm_set(Alarm, [_|T]) ->
+ alarm_set(Alarm, T);
+alarm_set(_Alarm, []) ->
+ false.
+
+process(suite) ->
+ [];
+process(doc) ->
+ ["Make sure memsup discovers a process grown very large"];
+process(Config) when is_list(Config) ->
+
+ %% Set a long memory check interval, we will force memory checks
+ %% instead
+ ?line ok = memsup:set_check_interval(60),
+
+ %% Collect data
+ MemData = memsup:get_memory_data(),
+ io:format("process: memsup:get_memory_data() = ~p~n", [MemData]),
+ ?line {_Total,_Free,{_,Bytes}} = MemData,
+
+ %% Start a new process larger than Worst
+ ?line WorsePid = spawn(fun() -> new_hog(Bytes) end),
+ ?t:sleep(?t:seconds(1)),
+
+ %% Initiate and wait for a new data collection
+ ?line ok = force_collection(),
+
+ %% Check that get_memory_data() returns updated result
+ ?line case memsup:get_memory_data() of
+ {_, _, {WorsePid, _MoreBytes}} ->
+ ok;
+ {_, _, BadWorst} ->
+ ?line ?t:fail({worst_pid, BadWorst})
+ end,
+
+ %% Reset memory check interval
+ ?line exit(WorsePid, done),
+ ?line ok = memsup:set_check_interval(1),
+ ok.
+
+new_hog(Bytes) ->
+ WordSize = erlang:system_info(wordsize),
+ N = (Bytes+200) div WordSize div 2,
+ List = lists:duplicate(N, a),
+ new_hog_1(List).
+
+new_hog_1(List) ->
+ receive
+ _Any -> exit(List)
+ end.
+
+config(suite) ->
+ [];
+config(doc) ->
+ ["Test configuration"];
+config(Config) when is_list(Config) ->
+
+ %% Change configuration parameters and make sure change is reflected
+ %% when memsup is restarted
+ ?line ok = application:set_env(os_mon, memory_check_interval, 2),
+ ?line ok =
+ application:set_env(os_mon, system_memory_high_watermark, 0.9),
+ ?line ok =
+ application:set_env(os_mon, process_memory_high_watermark, 0.1),
+ ?line ok = application:set_env(os_mon, memsup_helper_timeout, 35),
+ ?line ok = application:set_env(os_mon, memsup_system_only, true),
+
+ ?line ok = supervisor:terminate_child(os_mon_sup, memsup),
+ ?line {ok, _Child1} = supervisor:restart_child(os_mon_sup, memsup),
+
+ ?line 120000 = memsup:get_check_interval(),
+ ?line 90 = memsup:get_sysmem_high_watermark(),
+ ?line 10 = memsup:get_procmem_high_watermark(),
+ ?line 35 = memsup:get_helper_timeout(),
+
+ %% Also try this with bad parameter values, should be ignored
+ ?line ok = application:set_env(os_mon, memory_check_interval, 0.2),
+ ?line ok =
+ application:set_env(os_mon, system_memory_high_watermark, -0.9),
+ ?line ok =
+ application:set_env(os_mon, process_memory_high_watermark,-0.1),
+ ?line ok = application:set_env(os_mon, memsup_helper_timeout, 0.35),
+ ?line ok = application:set_env(os_mon, memsup_system_only, arne),
+
+ ?line ok = supervisor:terminate_child(os_mon_sup, memsup),
+ ?line {ok, _Child2} = supervisor:restart_child(os_mon_sup, memsup),
+
+ ?line 60000 = memsup:get_check_interval(),
+ ?line 80 = memsup:get_sysmem_high_watermark(),
+ ?line 5 = memsup:get_procmem_high_watermark(),
+ ?line 30 = memsup:get_helper_timeout(),
+
+ %% Reset configuration parameters
+ ?line ok = application:set_env(os_mon, memory_check_interval, 1),
+ ?line ok =
+ application:set_env(os_mon, system_memory_high_watermark, 0.8),
+ ?line ok =
+ application:set_env(os_mon, process_memory_high_watermark,0.05),
+ ?line ok = application:set_env(os_mon, memsup_helper_timeout, 30),
+ ?line ok = application:set_env(os_mon, memsup_system_only, false),
+
+ ok.
+
+unavailable(suite) ->
+ [];
+unavailable(doc) ->
+ ["Test correct behaviour when service is unavailable"];
+unavailable(Config) when is_list(Config) ->
+
+ %% Close memsup
+ ?line ok = application:set_env(os_mon, start_memsup, false),
+ ?line ok = supervisor:terminate_child(os_mon_sup, memsup),
+
+ %% Make sure all API functions return their dummy values
+ ?line {0,0,{_Pid,0}} = memsup:get_memory_data(),
+ ?line ok = application:set_env(os_mon, memsup_system_only, true),
+ ?line {0,0,undefined} = memsup:get_memory_data(),
+ ?line ok = application:set_env(os_mon, memsup_system_only, false),
+ ?line [] = memsup:get_system_memory_data(),
+ ?line 0 = memsup:get_os_wordsize(),
+ ?line 60000 = memsup:get_check_interval(),
+ ?line ok = memsup:set_check_interval(2),
+ ?line 5 = memsup:get_procmem_high_watermark(),
+ ?line ok = memsup:set_procmem_high_watermark(0.10),
+ ?line 80 = memsup:get_sysmem_high_watermark(),
+ ?line ok = memsup:set_sysmem_high_watermark(0.90),
+ ?line 30 = memsup:get_helper_timeout(),
+ ?line ok = memsup:set_helper_timeout(35),
+
+ %% Start memsup again,
+ ?line ok = application:set_env(os_mon, start_memsup, true),
+ ?line {ok, _Child} = supervisor:restart_child(os_mon_sup, memsup),
+
+ ok.
+
+timeout(suite) ->
+ [];
+timeout(doc) ->
+ ["Test stability of memsup when data collection times out"];
+timeout(Config) when is_list(Config) ->
+
+ %% Set a long memory check interval and memsup_helper timeout,
+ %% we will force memory checks instead and fake timeouts
+ ?line ok = memsup:set_check_interval(60),
+ ?line ok = memsup:set_helper_timeout(3600),
+
+ %% Provoke a timeout during memory collection
+ ?line memsup ! time_to_collect,
+ ?line memsup ! reg_collection_timeout,
+
+ %% Not much we can check though, except that memsup is still running
+ ?line {_,_,_} = memsup:get_memory_data(),
+
+ %% Provoke a timeout during extensive memory collection
+ %% We fake a gen_server:call/2 to be able to send a timeout message
+ %% while the request is being handled
+
+ %% Linux should be handled the same way as solaris.
+
+% TimeoutMsg = case ?t:os_type() of
+% {unix, sunos} -> ext_collection_timeout;
+% {unix, linux} -> reg_collection_timeout
+% end,
+
+ TimeoutMsg = ext_collection_timeout,
+
+ ?line Pid = whereis(memsup),
+ ?line Mref = erlang:monitor(process, Pid),
+ ?line Pid ! {'$gen_call', {self(), Mref}, get_system_memory_data},
+ ?line Pid ! TimeoutMsg,
+ receive
+ {Mref, []} ->
+ erlang:demonitor(Mref),
+ ?line ok;
+ {Mref, Res} ->
+ erlang:demonitor(Mref),
+ ?line ?t:fail({unexpected_result, Res});
+ {'DOWN', Mref, _, _, _} ->
+ ?line ?t:fail(no_result)
+ end,
+
+ %% Reset memory check interval and memsup_helper timeout
+ ?line ok = memsup:set_check_interval(1),
+ ?line ok = memsup:set_helper_timeout(30),
+ ?line memsup ! time_to_collect,
+
+ ?line [_|_] = memsup:get_system_memory_data(),
+
+ ok.
+
+port(suite) ->
+ [];
+port(doc) ->
+ ["Test that memsup handles a terminating port program"];
+port(Config) when is_list(Config) ->
+ ?line Str = os:cmd("ps -e | grep '[m]emsup'"),
+ case io_lib:fread("~s", Str) of
+ {ok, [Pid], _Rest} ->
+
+ %% Monitor memsup
+ ?line MonRef = erlang:monitor(process, memsup),
+ ?line {Total1,_Alloc1,_Worst1} = memsup:get_memory_data(),
+ ?line true = Total1>0,
+
+ %% Kill the port program
+ case os:cmd("kill -9 " ++ Pid) of
+ [] ->
+
+ %% memsup should now terminate
+ receive
+ {'DOWN', MonRef, _, _, {port_died, _Reason}} ->
+ ok;
+ {'DOWN', MonRef, _, _, Reason} ->
+ ?line ?t:fail({unexpected_exit_reason, Reason})
+ after
+ 3000 ->
+ ?line ?t:fail(still_alive)
+ end,
+
+ %% Give os_mon_sup time to restart memsup
+ ?t:sleep(?t:seconds(3)),
+ ?line {Total2,_Alloc2,_Worst2} =
+ memsup:get_memory_data(),
+ ?line true = Total2>0,
+
+ ok;
+
+ Line ->
+ erlang:demonitor(MonRef),
+ {skip, {not_killed, Line}}
+ end;
+ _ ->
+ {skip, {os_pid_not_found, Str}}
+ end.
+
+otp_5910(suite) ->
+ [];
+otp_5910(doc) ->
+ ["Test that alarms are cleared and not set twice"];
+otp_5910(Config) when is_list(Config) ->
+ Alarms =
+ [system_memory_high_watermark, process_memory_high_watermark],
+
+ %% Make sure memsup sets both alarms
+ ?line ok = application:set_env(os_mon, memory_check_interval, 60),
+ ?line ok = memsup:set_check_interval(60),
+ ?line SysThreshold = (memsup:get_sysmem_high_watermark()/100),
+ ?line ProcThreshold = (memsup:get_procmem_high_watermark()/100),
+
+ MemData = memsup:get_memory_data(),
+
+ io:format("otp_5910: memsup:get_memory_data() = ~p~n", [MemData]),
+ ?line {Total, Alloc, {_Pid, _Bytes}} = MemData,
+ ?line Pid = spawn_opt(fun() ->
+ receive
+ die -> ok
+ end
+ end, [{min_heap_size, 1000}]),
+ %% Create a process guaranteed to live, be constant and
+ %% break memsup process limit
+ ?line {memory, Bytes} = erlang:process_info(Pid,memory),
+ ?line SysUsage = Alloc/Total,
+ ?line ProcUsage = Bytes/Total,
+
+ if
+ SysUsage>SysThreshold ->
+ ok;
+ SysUsage=<SysThreshold ->
+ ?line ok = application:set_env(os_mon,
+ sys_mem_high_watermark,
+ 0.5 * SysUsage),
+ ?line ok = memsup:set_sysmem_high_watermark(0.5 * SysUsage)
+ end,
+ if
+ ProcUsage>ProcThreshold ->
+ ok;
+ ProcUsage=<ProcThreshold ->
+ ?line ok = application:set_env(os_mon,
+ proc_mem_high_watermark,
+ 0.5 * ProcUsage),
+ ?line ok = memsup:set_procmem_high_watermark(0.5 *ProcUsage)
+ end,
+ ?line ok = force_collection(),
+ ?t:sleep(?t:seconds(1)),
+ lists:foreach(fun(AlarmId) ->
+ case alarm_set(AlarmId) of
+ {true, _} -> ok;
+ false ->
+ ?line ?t:fail({alarm_not_set,
+ AlarmId})
+ end
+ end,
+ Alarms),
+
+ %% Kill guaranteed process...
+ Pid ! die,
+ %% Kill memsup
+ exit(whereis(memsup), faked_memsup_crash),
+ %% Wait a little to make sure memsup has been restarted,
+ %% then make sure the alarms are set once, but not twice
+ ?t:sleep(?t:seconds(1)),
+ ?line MemUsage = memsup:get_memory_data(),
+ SetAlarms = alarm_handler:get_alarms(),
+ case lists:foldl(fun(system_memory_high_watermark, {S, P}) ->
+ {S+1, P};
+ (process_memory_high_watermark, {S, P}) ->
+ {S, P+1};
+ (_AlarmId, Acc0) ->
+ Acc0
+ end,
+ {0, 0},
+ SetAlarms) of
+ {0, 0} ->
+ ok;
+ _ ->
+ ?line ?t:fail({bad_number_of_alarms, SetAlarms, MemUsage})
+ end,
+
+ %% Stop OS_Mon and make sure all memsup alarms are cleared
+ ?line ok = application:stop(os_mon),
+ ?t:sleep(?t:seconds(1)),
+ lists:foreach(fun(AlarmId) ->
+ case alarm_set(AlarmId) of
+ false -> ok;
+ {true, _} ->
+ ?line ?t:fail({alarm_is_set, AlarmId})
+ end
+ end,
+ Alarms),
+
+ %% Reset configuration and restart OS_Mon
+ ?line ok = application:set_env(os_mon,memory_check_interval,1),
+ ?line ok = application:set_env(os_mon,sys_mem_high_watermark,0.8),
+ ?line ok = application:set_env(os_mon,proc_mem_high_watermark,0.05),
+ ?line ok = application:start(os_mon),
+
+ ok.
+
+%%----------------------------------------------------------------------
+%% Auxiliary
+%%----------------------------------------------------------------------
+
+force_collection() ->
+ erlang:trace(whereis(memsup), true, ['receive']),
+ memsup ! time_to_collect,
+ TimerRef = erlang:send_after(5000, self(), timeout),
+ force_collection(TimerRef).
+
+force_collection(TimerRef) ->
+ receive
+ {trace, _Pid, 'receive', {collected_sys, _Sys}} ->
+ erlang:cancel_timer(TimerRef),
+ erlang:trace(whereis(memsup), false, ['receive']),
+ flush(),
+ ok;
+ {trace, _Pid, 'receive', reg_collection_timeout} ->
+ erlang:cancel_timer(TimerRef),
+ erlang:trace(whereis(memsup), false, ['receive']),
+ flush(),
+ collection_timeout;
+ timout ->
+ erlang:trace(whereis(memsup), false, ['receive']),
+ flush(),
+ timeout;
+ _Msg ->
+ force_collection(TimerRef)
+ end.
+
+flush() ->
+ receive
+ {trace, _, _, _} ->
+ flush();
+ timeout ->
+ flush()
+ after 0 ->
+ ok
+ end.
diff --git a/lib/os_mon/test/os_mon.spec b/lib/os_mon/test/os_mon.spec
new file mode 100644
index 0000000000..bdae523795
--- /dev/null
+++ b/lib/os_mon/test/os_mon.spec
@@ -0,0 +1 @@
+{topcase, {dir, "../os_mon_test"}}.
diff --git a/lib/os_mon/test/os_mon_SUITE.erl b/lib/os_mon/test/os_mon_SUITE.erl
new file mode 100644
index 0000000000..ce52271ff8
--- /dev/null
+++ b/lib/os_mon/test/os_mon_SUITE.erl
@@ -0,0 +1,89 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(os_mon_SUITE).
+-include("test_server.hrl").
+
+%% Test server specific exports
+-export([all/1]).
+-export([init_per_testcase/2, fin_per_testcase/2]).
+
+%% Test cases
+-export([app_file/1, config/1]).
+
+%% Default timetrap timeout (set in init_per_testcase)
+-define(default_timeout, ?t:minutes(1)).
+
+init_per_testcase(_Case, Config) ->
+ Dog = test_server:timetrap(?default_timeout),
+ [{watchdog, Dog}|Config].
+
+fin_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ test_server:timetrap_cancel(Dog),
+ ok.
+
+all(suite) ->
+ case ?t:os_type() of
+ {unix, sunos} -> [app_file, config];
+ _OS -> [app_file]
+ end.
+
+app_file(suite) ->
+ [];
+app_file(doc) ->
+ ["Testing .app file"];
+app_file(Config) when is_list(Config) ->
+ ?line ok = test_server:app_test(os_mon),
+ ok.
+
+config(suite) ->
+ [];
+config(doc) ->
+ ["Test OS_Mon configuration"];
+config(Config) when is_list(Config) ->
+
+ IsReg = fun(Name) -> is_pid(whereis(Name)) end,
+ IsNotReg = fun(Name) -> undefined == whereis(Name) end,
+
+ ?line ok = application:start(os_mon),
+ ?line true = lists:all(IsReg, [cpu_sup, disksup, memsup]),
+ ?line ok = application:stop(os_mon),
+
+ ?line ok = application:set_env(os_mon, start_cpu_sup, false),
+ ?line ok = application:start(os_mon),
+ ?line true = lists:all(IsReg, [disksup, memsup]),
+ ?line true = IsNotReg(cpu_sup),
+ ?line ok = application:stop(os_mon),
+ ?line ok = application:set_env(os_mon, start_cpu_sup, true),
+
+ ?line ok = application:set_env(os_mon, start_disksup, false),
+ ?line ok = application:start(os_mon),
+ ?line true = lists:all(IsReg, [cpu_sup, memsup]),
+ ?line true = IsNotReg(disksup),
+ ?line ok = application:stop(os_mon),
+ ?line ok = application:set_env(os_mon, start_disksup, true),
+
+ ?line ok = application:set_env(os_mon, start_memsup, false),
+ ?line ok = application:start(os_mon),
+ ?line true = lists:all(IsReg, [cpu_sup, disksup]),
+ ?line true = IsNotReg(memsup),
+ ?line ok = application:stop(os_mon),
+ ?line ok = application:set_env(os_mon, start_memsup, true),
+
+ ok.
diff --git a/lib/os_mon/test/os_mon_conf.erl b/lib/os_mon/test/os_mon_conf.erl
new file mode 100644
index 0000000000..5c1fa43047
--- /dev/null
+++ b/lib/os_mon/test/os_mon_conf.erl
@@ -0,0 +1,28 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(os_mon_conf).
+-export([init/1,fin/1]).
+
+init(Conf) ->
+ RetVal = application:start(os_mon,temporary),
+ [{os_mon,RetVal}|Conf].
+
+fin(Conf) ->
+ application:stop(os_mon),
+ lists:keydelete(os_mon,1,Conf).
diff --git a/lib/os_mon/test/os_mon_mib_SUITE.erl b/lib/os_mon/test/os_mon_mib_SUITE.erl
new file mode 100644
index 0000000000..a1d463030a
--- /dev/null
+++ b/lib/os_mon/test/os_mon_mib_SUITE.erl
@@ -0,0 +1,746 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(os_mon_mib_SUITE).
+
+%-define(STANDALONE,1).
+
+-ifdef(STANDALONE).
+-define(line,erlang:display({line,?LINE}),).
+-define(config(A,B), config(A,B)).
+-else.
+-include("test_server.hrl").
+-include_lib("os_mon/include/OTP-OS-MON-MIB.hrl").
+-include_lib("snmp/include/snmp_types.hrl").
+-endif.
+
+% Test server specific exports
+-export([all/1, init_per_suite/1, end_per_suite/1,
+ init_per_testcase/2, end_per_testcase/2]).
+
+
+% Test cases must be exported.
+-export([update_load_table/1]).
+
+-export([get_mem_sys_mark/1, get_mem_proc_mark/1, get_disk_threshold/1,
+ get_load_table/1, get_next_load_table/1, get_disk_table/1,
+ get_next_disk_table/1, real_snmp_request/1, load_unload/1]).
+
+-export([sys_tot_mem/1, sys_used_mem/1, large_erl_process/1,
+ large_erl_process_mem/1, cpu_load/1, cpu_load5/1, cpu_load15/1,
+ os_wordsize/1, sys_tot_mem64/1, sys_used_mem64/1,
+ large_erl_process_mem64/1, disk_descr/1, disk_kbytes/1,
+ disk_capacity/1]).
+
+-export([tickets/1]).
+-export([otp_6351/1, otp_7441/1]).
+
+-define(TRAP_UDP, 5000).
+-define(AGENT_UDP, 4000).
+-define(CONF_FILE_VER, [v2]).
+-define(SYS_NAME, "Test os_mon_mibs").
+-define(MAX_MSG_SIZE, 484).
+-define(ENGINE_ID, "mgrEngine").
+-define(MGR_PORT, 5001).
+
+%%---------------------------------------------------------------------
+-ifdef(STANDALONE).
+-export([run/0]).
+run() ->
+ catch init_per_suite([]),
+ Ret = (catch update_load_table([])),
+ catch end_per_suite([]),
+ Ret.
+-else.
+
+init_per_testcase(_Case, Config) when is_list(Config) ->
+ Dog = test_server:timetrap(test_server:minutes(6)),
+ [{watchdog, Dog}|Config].
+
+end_per_testcase(_Case, Config) when is_list(Config) ->
+ Dog = ?config(watchdog, Config),
+ test_server:timetrap_cancel(Dog),
+ Config.
+
+all(doc) ->
+ ["Test os_mon mibs and provided instrumentation functions."];
+
+all(suite) ->
+ [load_unload, get_mem_sys_mark, get_mem_proc_mark,
+ get_disk_threshold, get_load_table, get_next_load_table,
+ get_disk_table, get_next_disk_table, real_snmp_request,
+ update_load_table, tickets].
+
+tickets(suite) ->
+ [otp_6351, otp_7441].
+
+-endif.
+%%---------------------------------------------------------------------
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config) -> Config
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Description: Initiation before the whole suite
+%%
+%% Note: This function is free to add any key/value pairs to the Config
+%% variable, but should NOT alter/remove any existing entries.
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ ?line application:start(sasl),
+ ?line application:start(mnesia),
+ ?line application:start(os_mon),
+
+ %% Create initial configuration data for the snmp application
+ ?line PrivDir = ?config(priv_dir, Config),
+ ?line ConfDir = filename:join(PrivDir, "conf"),
+ ?line DbDir = filename:join(PrivDir,"db"),
+ ?line MgrDir = filename:join(PrivDir,"mgr"),
+
+ ?line file:make_dir(ConfDir),
+ ?line file:make_dir(DbDir),
+ ?line file:make_dir(MgrDir),
+
+ {ok, HostName} = inet:gethostname(),
+ {ok, Addr} = inet:getaddr(HostName, inet),
+
+ ?line snmp_config:write_agent_snmp_files(ConfDir, ?CONF_FILE_VER,
+ tuple_to_list(Addr), ?TRAP_UDP,
+ tuple_to_list(Addr),
+ ?AGENT_UDP, ?SYS_NAME),
+
+ ?line snmp_config:write_manager_snmp_files(MgrDir, tuple_to_list(Addr),
+ ?MGR_PORT, ?MAX_MSG_SIZE,
+ ?ENGINE_ID, [], [], []),
+
+ %% To make sure application:set_env is not overwritten by any
+ %% app-file settings.
+ ?line ok = application:load(snmp),
+
+ ?line application:set_env(snmp, agent, [{db_dir, DbDir},
+ {config, [{dir, ConfDir}]},
+ {agent_type, master},
+ {agent_verbosity, trace},
+ {net_if, [{verbosity, trace}]}]),
+ ?line application:set_env(snmp, manager, [{config, [{dir, MgrDir},
+ {db_dir, MgrDir},
+ {verbosity, trace}]},
+ {server, [{verbosity, trace}]},
+ {net_if, [{verbosity, trace}]},
+ {versions, [v1, v2, v3]}]),
+ application:start(snmp),
+
+ %% Load the mibs that should be tested
+ otp_mib:load(snmp_master_agent),
+ os_mon_mib:load(snmp_master_agent),
+
+ [{agent_ip, Addr}| Config].
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config) -> _
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Description: Cleanup after the whole suite
+%%--------------------------------------------------------------------
+end_per_suite(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ ConfDir = filename:join(PrivDir,"conf"),
+ DbDir = filename:join(PrivDir,"db"),
+ MgrDir = filename:join(PrivDir, "mgr"),
+
+ %% Uload mibs
+ snmpa:unload_mibs(snmp_master_agent,["OTP-OS-MON-MIB"]),
+ otp_mib:unload(snmp_master_agent),
+
+ %% Clean up
+ application:stop(snmp),
+ application:stop(mnesia),
+ application:stop(os_mon),
+
+ del_dir(ConfDir),
+ del_dir(DbDir),
+ (catch del_dir(MgrDir)),
+ ok.
+
+%%---------------------------------------------------------------------
+%% Test cases
+%%---------------------------------------------------------------------
+load_unload(doc) ->
+ ["Test to unload and the reload the OTP.mib "];
+load_unload(suite) -> [];
+load_unload(Config) when list(Config) ->
+ ?line os_mon_mib:unload(snmp_master_agent),
+ ?line os_mon_mib:load(snmp_master_agent),
+ ok.
+%%---------------------------------------------------------------------
+
+update_load_table(doc) ->
+ ["check os_mon_mib:update_load_table error handling"];
+update_load_table(suite) ->
+ [];
+update_load_table(Config) when is_list(Config) ->
+ ?line Node = start_node(),
+ ?line ok = rpc:call(Node,application,start,[sasl]),
+ ?line ok = rpc:call(Node,application,start,[os_mon]),
+ ?line ok = os_mon_mib:update_load_table(),
+ ?line rpc:call(Node,application,stop,[os_mon]),
+ ?line ok = os_mon_mib:update_load_table(),
+ ?line stop_node(Node),
+ ok.
+
+otp_6351(doc) ->
+ ["like update_load_table, when memsup_system_only==true"];
+otp_6351(suite) ->
+ [];
+otp_6351(Config) when is_list(Config) ->
+ ?line Node = start_node(),
+ ?line ok = rpc:call(Node,application,start,[sasl]),
+ ?line ok = rpc:call(Node,application,load,[os_mon]),
+ ?line ok = rpc:call(Node,application,set_env,
+ [os_mon,memsup_system_only,true]),
+ ?line ok = rpc:call(Node,application,start,[os_mon]),
+ ?line Res = rpc:call(Node,os_mon_mib,get_load,[Node]),
+ if
+ is_tuple(Res), element(1, Res)==loadTable ->
+ ?line ok;
+ true ->
+ ?line ?t:fail(Res)
+ end,
+ ?line rpc:call(Node,application,stop,[os_mon]),
+ ?line stop_node(Node),
+ ok.
+
+
+
+
+%%---------------------------------------------------------------------
+get_mem_sys_mark(doc) ->
+ ["Simulates a get call to test the instrumentation function "
+ "for the loadMemorySystemWatermark variable."];
+get_mem_sys_mark(suite) ->
+ [];
+get_mem_sys_mark(Config) when is_list(Config) ->
+ case os_mon_mib:mem_sys_mark(get) of
+ {value, SysMark} when is_integer(SysMark) ->
+ ok;
+ _ ->
+ ?line test_server:fail(sys_mark_value_not_integer)
+ end.
+%%---------------------------------------------------------------------
+get_mem_proc_mark(doc) ->
+ ["Simulates a get call to test the instrumentation function "
+ "for the loadMemoryErlProcWatermark variable."];
+get_mem_proc_mark(suite) ->
+ [];
+get_mem_proc_mark(Config) when is_list(Config) ->
+ case os_mon_mib:mem_proc_mark(get) of
+ {value, ProcMark} when is_integer(ProcMark) ->
+ ok;
+ _ ->
+ ?line test_server:fail(proc_mark_value_not_integer)
+ end.
+%%---------------------------------------------------------------------
+get_disk_threshold(doc) ->
+ ["Simulates a get call to test the instrumentation function "
+ "for the diskAlmostFullThreshold variable."];
+get_disk_threshold(suite) ->
+ [];
+get_disk_threshold(Config) when is_list(Config) ->
+ case os_mon_mib:disk_threshold(get) of
+ {value, ProcMark} when is_integer(ProcMark) ->
+ ok;
+ _ ->
+ ?line test_server:fail(disk_threshold_value_not_integer)
+ end.
+%%---------------------------------------------------------------------
+
+%%% Note that when we have a string key, as in loadTable, the
+%%% instrumentation will deal with the [length(String), String]. We
+%%% have to know about this, when short cutting SNMP and calling
+%%% instrumentation functions directly as done in most test cases in
+%%% this test suite
+
+get_load_table(doc) ->
+ ["Simulates get calls to test the instrumentation function "
+ "for the loadTable"];
+get_load_table(suite) ->
+ [];
+get_load_table(Config) when is_list(Config) ->
+
+ NodeStr = atom_to_list(node()),
+ NodeLen = length(NodeStr),
+
+ {_, _, {Pid, _}} = memsup:get_memory_data(),
+ PidStr = lists:flatten(io_lib:format("~w", [Pid])),
+ ?line [{value, NodeStr},{value, PidStr}] =
+ os_mon_mib:load_table(get, [NodeLen | NodeStr],
+ [?loadErlNodeName, ?loadLargestErlProcess]),
+
+ ?line Values = os_mon_mib:load_table(get, [NodeLen | NodeStr] ,
+ [?loadSystemTotalMemory,
+ ?loadSystemUsedMemory,
+ ?loadLargestErlProcessUsedMemory,
+ ?loadCpuLoad,
+ ?loadCpuLoad5,
+ ?loadCpuLoad15,
+ ?loadOsWordsize,
+ ?loadSystemTotalMemory64,
+ ?loadSystemUsedMemory64,
+ ?loadLargestErlProcessUsedMemory64]),
+
+ IsInt = fun({value, Val}) when is_integer(Val) ->
+ true;
+ (_) ->
+ false
+ end,
+
+ NewValues = lists:filter(IsInt, Values),
+
+ case length(NewValues) of
+ 10 ->
+ ok;
+ _ ->
+ ?line test_server:fail(value_not_integer)
+ end,
+
+ ?line [{noValue,noSuchInstance}, {noValue,noSuchInstance},
+ {noValue,noSuchInstance}, {noValue,noSuchInstance},
+ {noValue,noSuchInstance}, {noValue,noSuchInstance},
+ {noValue,noSuchInstance}, {noValue,noSuchInstance},
+ {noValue,noSuchInstance}, {noValue,noSuchInstance},
+ {noValue,noSuchInstance}, {noValue,noSuchInstance}] =
+ os_mon_mib:load_table(get, [3, 102, 111, 111],
+ [?loadErlNodeName,
+ ?loadSystemTotalMemory,
+ ?loadSystemUsedMemory,
+ ?loadLargestErlProcess,
+ ?loadLargestErlProcessUsedMemory,
+ ?loadCpuLoad,
+ ?loadCpuLoad5,
+ ?loadCpuLoad15,
+ ?loadOsWordsize,
+ ?loadSystemTotalMemory64,
+ ?loadSystemUsedMemory64,
+ ?loadLargestErlProcessUsedMemory64]),
+
+ ok.
+%%---------------------------------------------------------------------
+get_next_load_table(doc) ->
+ ["Simulates get_next calls to test the instrumentation function "
+ "for the loadTable"];
+get_next_load_table(suite) ->
+ [ sys_tot_mem,
+ sys_used_mem,
+ large_erl_process,
+ large_erl_process_mem,
+ cpu_load,
+ cpu_load5,
+ cpu_load15,
+ os_wordsize,
+ sys_tot_mem64,
+ sys_used_mem64,
+ large_erl_process_mem64].
+
+sys_tot_mem(doc) ->
+ [];
+sys_tot_mem(suite) ->
+ [];
+sys_tot_mem(Config) when is_list(Config) ->
+ ?line [{[?loadSystemTotalMemory, Len | NodeStr], Mem}] =
+ os_mon_mib:load_table(get_next, [], [?loadSystemTotalMemory]),
+ ?line Len = length(NodeStr),
+ ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]),
+
+ case Mem of
+ Mem when is_integer(Mem) ->
+ ok;
+ _ ->
+ ?line test_server:fail(sys_tot_mem_value_not_integer)
+ end.
+
+sys_used_mem(doc) ->
+ [];
+sys_used_mem(suite) -> [];
+sys_used_mem(Config) when is_list(Config) ->
+ ?line [{[?loadSystemUsedMemory, Len | NodeStr], Mem}] =
+ os_mon_mib:load_table(get_next,[], [?loadSystemUsedMemory]),
+ ?line Len = length(NodeStr),
+ ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]),
+
+ case Mem of
+ Mem when is_integer(Mem) ->
+ ok;
+ _ ->
+ ?line test_server:fail(sys_used_mem_value_not_integer)
+ end.
+
+large_erl_process(doc) ->
+ [];
+large_erl_process(suite) ->
+ [];
+large_erl_process(Config) when is_list(Config) ->
+ {_, _, {Pid, _}} = memsup:get_memory_data(),
+ PidStr = lists:flatten(io_lib:format("~w", [Pid])),
+ ?line [{[?loadLargestErlProcess, Len | NodeStr], PidStr}] =
+ os_mon_mib:load_table(get_next,[], [?loadLargestErlProcess]),
+ ?line Len = length(NodeStr),
+ ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]),
+ ok.
+
+large_erl_process_mem(doc) ->
+ [];
+large_erl_process_mem(suite) ->
+ [];
+large_erl_process_mem(Config) when is_list(Config) ->
+
+ ?line [{[?loadLargestErlProcessUsedMemory, Len | NodeStr], Mem}] =
+ os_mon_mib:load_table(get_next,[],
+ [?loadLargestErlProcessUsedMemory]),
+ ?line Len = length(NodeStr),
+ ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]),
+
+ case Mem of
+ Mem when is_integer(Mem) ->
+ ok;
+ _ ->
+ ?line test_server:fail(erl_pid_mem_value_not_integer)
+ end.
+
+cpu_load(doc) ->
+ [];
+cpu_load(suite) ->
+ [];
+cpu_load(Config) when list(Config) ->
+ ?line [{[?loadCpuLoad, Len | NodeStr], Load}] =
+ os_mon_mib:load_table(get_next,[], [?loadCpuLoad]),
+ ?line Len = length(NodeStr),
+ ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]),
+
+ case Load of
+ Load when is_integer(Load) ->
+ ok;
+ _ ->
+ ?line test_server:fail(cpu_load_value_not_integer)
+ end.
+
+cpu_load5(doc) ->
+ [];
+cpu_load5(suite) ->
+ [];
+cpu_load5(Config) when is_list(Config) ->
+ ?line [{[?loadCpuLoad5, Len | NodeStr], Load}] =
+ os_mon_mib:load_table(get_next,[], [?loadCpuLoad5]),
+ ?line Len = length(NodeStr),
+ ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]),
+
+ case Load of
+ Load when is_integer(Load) ->
+ ok;
+ _ ->
+ ?line test_server:fail(cpu_load5_value_not_integer)
+ end.
+
+cpu_load15(doc) ->
+ [];
+cpu_load15(suite) ->
+ [];
+cpu_load15(Config) when is_list(Config) ->
+ ?line [{[?loadCpuLoad15, Len | NodeStr], Load}] =
+ os_mon_mib:load_table(get_next,[], [?loadCpuLoad15]),
+ ?line Len = length(NodeStr),
+ ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]),
+
+ case Load of
+ Load when is_integer(Load) ->
+ ok;
+ _ ->
+ ?line test_server:fail(cpu_load15_value_not_integer)
+ end.
+
+os_wordsize(doc) ->
+ [];
+os_wordsize(suite) ->
+ [];
+os_wordsize(Config) when is_list(Config) ->
+ ?line [{[?loadOsWordsize, Len | NodeStr], Wordsize}] =
+ os_mon_mib:load_table(get_next,[], [?loadOsWordsize]),
+ ?line Len = length(NodeStr),
+ ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]),
+
+ case Wordsize of
+ Wordsize when is_integer(Wordsize) ->
+ ok;
+ _ ->
+ ?line test_server:fail(os_wordsize_value_not_integer)
+ end.
+
+sys_tot_mem64(doc) ->
+ [];
+sys_tot_mem64(suite) ->
+ [];
+sys_tot_mem64(Config) when is_list(Config) ->
+ ?line [{[?loadSystemTotalMemory64, Len | NodeStr], Mem}] =
+ os_mon_mib:load_table(get_next, [], [?loadSystemTotalMemory64]),
+ ?line Len = length(NodeStr),
+ ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]),
+
+ case Mem of
+ Mem when is_integer(Mem) ->
+ ok;
+ _ ->
+ ?line test_server:fail(sys_tot_mem_value_not_integer)
+ end.
+
+sys_used_mem64(doc) ->
+ [];
+sys_used_mem64(suite) -> [];
+sys_used_mem64(Config) when is_list(Config) ->
+ ?line [{[?loadSystemUsedMemory64, Len | NodeStr], Mem}] =
+ os_mon_mib:load_table(get_next,[], [?loadSystemUsedMemory64]),
+ ?line Len = length(NodeStr),
+ ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]),
+
+ case Mem of
+ Mem when is_integer(Mem) ->
+ ok;
+ _ ->
+ ?line test_server:fail(sys_used_mem_value_not_integer)
+ end.
+
+large_erl_process_mem64(doc) ->
+ [];
+large_erl_process_mem64(suite) ->
+ [];
+large_erl_process_mem64(Config) when is_list(Config) ->
+
+ ?line [{[?loadLargestErlProcessUsedMemory64, Len | NodeStr], Mem}] =
+ os_mon_mib:load_table(get_next,[],
+ [?loadLargestErlProcessUsedMemory64]),
+ ?line Len = length(NodeStr),
+ ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]),
+
+ case Mem of
+ Mem when is_integer(Mem) ->
+ ok;
+ _ ->
+ ?line test_server:fail(erl_pid_mem_value_not_integer)
+ end.
+%%---------------------------------------------------------------------
+get_disk_table(doc) ->
+ ["Simulates get calls to test the instrumentation function "
+ "for the diskTable."];
+get_disk_table(suite) ->
+ [];
+get_disk_table(Config) when is_list(Config) ->
+
+ DiskData = disksup:get_disk_data(),
+ DiskDataLen = length(DiskData),
+
+ if
+ DiskDataLen > 0 ->
+ ?line [{value, Value}] =
+ os_mon_mib:disk_table(get, [1,1], [?diskDescr]),
+
+ case is_list(Value) of
+ true ->
+ ok;
+ false ->
+ ?line test_server:fail(value_not_a_string)
+ end,
+
+ ?line Values = os_mon_mib:disk_table(get, [1,1],
+ [?diskId,
+ ?diskKBytes,
+ ?diskCapacity]),
+
+ IsInt = fun({value, Val}) when is_integer(Val) ->
+ true;
+ (_) ->
+ false
+ end,
+
+ NewValues = lists:filter(IsInt, Values),
+
+ case length(NewValues) of
+ 3 ->
+ ok;
+ _ ->
+ ?line test_server:fail(value_not_integer)
+ end
+ end,
+
+ ?line [{noValue,noSuchInstance}, {noValue,noSuchInstance},
+ {noValue,noSuchInstance}, {noValue,noSuchInstance}] =
+ os_mon_mib:disk_table(get, [1, DiskDataLen + 1], [?diskId,
+ ?diskDescr,
+ ?diskKBytes,
+ ?diskCapacity]),
+
+ ok.
+
+%%---------------------------------------------------------------------
+get_next_disk_table(doc) ->
+ ["Simulates get_next calls to test the instrumentation function "
+ "for the diskTable."];
+get_next_disk_table(suite) ->
+ [disk_descr, disk_kbytes, disk_capacity].
+
+disk_descr(doc) ->
+ [];
+disk_descr(suite) ->
+ [];
+disk_descr(Config) when is_list(Config) ->
+ ?line [{[?diskDescr, 1,1], Descr}] =
+ os_mon_mib:disk_table(get_next, [], [?diskDescr]),
+
+ case Descr of
+ Descr when is_list(Descr) ->
+ ok;
+ _ ->
+ ?line test_server:fail(disk_descr_value_not_a_string)
+ end.
+
+disk_kbytes(doc) ->
+ [];
+disk_kbytes(suite) -> [];
+disk_kbytes(Config) when is_list(Config) ->
+ ?line [{[?diskKBytes, 1,1], Kbytes}] =
+ os_mon_mib:disk_table(get_next,[], [?diskKBytes]),
+
+ case Kbytes of
+ Kbytes when is_integer(Kbytes) ->
+ ok;
+ _ ->
+ ?line test_server:fail(disk_kbytes_value_not_integer)
+ end.
+
+
+disk_capacity(doc) ->
+ [];
+disk_capacity(suite) -> [];
+disk_capacity(Config) when is_list(Config) ->
+ ?line [{[?diskCapacity, 1,1], Capacity}] =
+ os_mon_mib:disk_table(get_next,[], [?diskCapacity]),
+
+ case Capacity of
+ Capacity when is_integer(Capacity) ->
+ ok;
+ _ ->
+ ?line test_server:fail(disk_capacity_value_not_integer)
+ end.
+
+%%---------------------------------------------------------------------
+real_snmp_request(doc) ->
+ ["Starts an snmp manager and sends a real snmp-reques. i.e. "
+ "sends a udp message on the correct format."];
+real_snmp_request(suite) -> [];
+real_snmp_request(Config) when list(Config) ->
+ Agent_ip = ?config(agent_ip, Config),
+
+ ?line ok = snmpm:register_user(os_mon_mib_test, snmpm_user_default, []),
+ ?line ok = snmpm:register_agent(os_mon_mib_test, Agent_ip, ?AGENT_UDP),
+
+ NodStr = atom_to_list(node()),
+ Len = length(NodStr),
+ {_, _, {Pid, _}} = memsup:get_memory_data(),
+ PidStr = lists:flatten(io_lib:format("~w", [Pid])),
+ io:format("FOO: ~p~n", [PidStr]),
+ ?line ok = snmp_get(Agent_ip,
+ [?loadEntry ++
+ [?loadLargestErlProcess, Len | NodStr]],
+ PidStr),
+ ?line ok = snmp_get_next(Agent_ip,
+ [?loadEntry ++
+ [?loadSystemUsedMemory, Len | NodStr]],
+ ?loadEntry ++ [?loadSystemUsedMemory + 1, Len
+ | NodStr], PidStr),
+ ?line ok = snmp_set(Agent_ip, [?loadEntry ++
+ [?loadLargestErlProcess, Len | NodStr]],
+ s, "<0.101.0>"),
+ ok.
+
+otp_7441(doc) ->
+ ["Starts an snmp manager and requests total memory. Was previously
+ integer32 which was errornous on 64 bit machines."];
+otp_7441(suite) ->
+ [];
+otp_7441(Config) when is_list(Config) ->
+ Agent_ip = ?config(agent_ip, Config),
+
+
+ NodStr = atom_to_list(node()),
+ Len = length(NodStr),
+ Oids = [Oid|_] = [?loadEntry ++ [?loadSystemTotalMemory, Len | NodStr]],
+ ?line { ok, {noError,0,[#varbind{oid = Oid, variabletype = 'Unsigned32'}]}, _} =
+ snmpm:g(os_mon_mib_test, Agent_ip, ?AGENT_UDP, Oids),
+
+ ok.
+
+%%---------------------------------------------------------------------
+%% Internal functions
+%%---------------------------------------------------------------------
+-ifdef(STANDALONE).
+config(priv_dir,_) ->
+ "/tmp".
+
+start_node() ->
+ Host = hd(tl(string:tokens(atom_to_list(node()),"@"))),
+ {ok,Node} = slave:start(Host,testnisse),
+ net_adm:ping(testnisse),
+ Node.
+
+
+stop_node(Node) ->
+ rpc:call(Node,erlang,halt,[]).
+-else.
+start_node() ->
+ ?line Pa = filename:dirname(code:which(?MODULE)),
+ ?line {ok,Node} = test_server:start_node(testnisse, slave,
+ [{args, " -pa " ++ Pa}]),
+ Node.
+
+stop_node(Node) ->
+ test_server:stop_node(Node).
+
+-endif.
+
+del_dir(Dir) ->
+ io:format("Deleting: ~s~n",[Dir]),
+ {ok, Files} = file:list_dir(Dir),
+ FullPathFiles = lists:map(fun(File) -> filename:join(Dir, File) end,
+ Files),
+ lists:foreach({file, delete}, FullPathFiles),
+ file:del_dir(Dir).
+
+%%---------------------------------------------------------------------
+snmp_get(Agent_ip, Oids = [Oid |_], Result) ->
+ ?line {ok,{noError,0,[#varbind{oid = Oid,
+ variabletype = 'OCTET STRING',
+ value = Result}]}, _} =
+ snmpm:g(os_mon_mib_test, Agent_ip, ?AGENT_UDP, Oids),
+ ok.
+
+snmp_get_next(Agent_ip, Oids, NextOid, Result) ->
+ ?line {ok,{noError,0,[#varbind{oid = NextOid,
+ variabletype = 'OCTET STRING',
+ value = Result}]},_} =
+ snmpm:gn(os_mon_mib_test, Agent_ip, ?AGENT_UDP, Oids),
+ ok.
+
+snmp_set(Agent_ip, Oid, ValuType, Value) ->
+ ?line {ok, {notWritable, _, _}, _} =
+ snmpm:s(os_mon_mib_test,Agent_ip,?AGENT_UDP,[{Oid, ValuType, Value}]),
+ ok.
diff --git a/lib/os_mon/test/os_sup_SUITE.erl b/lib/os_mon/test/os_sup_SUITE.erl
new file mode 100644
index 0000000000..25041f968d
--- /dev/null
+++ b/lib/os_mon/test/os_sup_SUITE.erl
@@ -0,0 +1,189 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(os_sup_SUITE).
+-include("test_server.hrl").
+
+%% Test server specific exports
+-export([all/1]).
+-export([init_per_suite/1, end_per_suite/1]).
+-export([init_per_testcase/2, end_per_testcase/2]).
+
+%% Test cases
+-export([message/1]).
+-export([config/1, port/1]).
+
+%% Default timetrap timeout (set in init_per_testcase)
+-define(default_timeout, ?t:minutes(1)).
+
+-define(TAG, test_tag).
+-define(MFA, {?MODULE, test_mfa, [?TAG]}).
+
+-export([test_mfa/2]).
+
+init_per_suite(Config) when is_list(Config) ->
+ spawn(fun() -> message_receptor() end),
+ ?line application:load(os_mon),
+ ?line ok = application:set_env(os_mon, start_os_sup, true),
+ ?line ok = application:set_env(os_mon, os_sup_mfa, ?MFA),
+ ?line ok = application:set_env(os_mon, os_sup_enable, false),
+ ?line ok = application:start(os_mon),
+ Config.
+
+end_per_suite(Config) when is_list(Config) ->
+ ?line application:stop(os_mon),
+ ?line ok = application:set_env(os_mon, start_os_sup, false),
+ MFA = {os_sup, error_report, [std_error]},
+ ?line ok = application:set_env(os_mon, os_sup_mfa, MFA),
+ ?line ok = application:set_env(os_mon, os_sup_enable, true),
+ ?line exit(whereis(message_receptor), done),
+ Config.
+
+init_per_testcase(_Case, Config) ->
+ Dog = ?t:timetrap(?default_timeout),
+ [{watchdog,Dog} | Config].
+
+end_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+all(suite) ->
+ case ?t:os_type() of
+ {unix, sunos} ->
+ [message, config, port];
+ {win32, _OSname} ->
+ [message];
+ OS ->
+ Str = io_lib:format("os_sup not available for ~p", [OS]),
+ {skip, lists:flatten(Str)}
+ end.
+
+message(suite) ->
+ [];
+message(doc) ->
+ ["Test OS message handling"];
+message(Config) when is_list(Config) ->
+
+ %% Fake an OS message
+ Data = "10H11386278426HSystem4HTest5HError5HTesto",
+ ?line os_sup_server ! {faked_port, {data, Data}},
+
+ %% Check with message_receptor that it has been received
+ ?t:sleep(?t:seconds(1)),
+ Msg =
+ case ?t:os_type() of
+ {unix, sunos} ->
+ {?TAG, Data};
+ {win32, _} ->
+ {?TAG,{{1138,627842,0},"System","Test","Error","Testo"}}
+ end,
+ ?line message_receptor ! {check, self(), Msg},
+ receive
+ {result, true} ->
+ ok;
+ {result, Rec} ->
+ ?t:fail({no_message, Rec})
+ end,
+
+ ok.
+
+config(suite) ->
+ [];
+config(doc) ->
+ ["Test configuration"];
+config(Config) when is_list(Config) ->
+
+ %% os_sup_enable==true and os_sup_own/os_sup_syslogconf cannot
+ %% be tested as test_server is not running is root
+
+ %% os_sup_mfa is already tested, sort of (in init_per_suite)
+
+ %% os_sup_errortag should be tested, however
+
+ ok.
+
+port(suite) ->
+ [];
+port(doc) ->
+ ["Test that os_sup handles a terminating port program"];
+port(Config) when is_list(Config) ->
+ ?line Str = os:cmd("ps -e | grep '[f]errule'"),
+ case io_lib:fread("~s", Str) of
+ {ok, [Pid], _Rest} ->
+
+ %% Monitor os_sup_server
+ ?line MonRef = erlang:monitor(process, os_sup_server),
+
+ %% Kill the port program
+ case os:cmd("kill -9 " ++ Pid) of
+ [] ->
+
+ %% os_sup_server should now terminate
+ receive
+ {'DOWN', MonRef, _, _, {port_died, _Reason}} ->
+ ok;
+ {'DOWN', MonRef, _, _, Reason} ->
+ ?line ?t:fail({unexpected_exit_reason, Reason})
+ after
+ 3000 ->
+ ?line ?t:fail(still_alive)
+ end,
+
+ %% Give os_mon_sup time to restart os_sup
+ ?t:sleep(?t:seconds(3)),
+ ?line true = is_pid(whereis(os_sup_server)),
+
+ ok;
+
+ Line ->
+ erlang:demonitor(MonRef),
+ {skip, {not_killed, Line}}
+ end;
+ _ ->
+ {skip, {os_pid_not_found}}
+ end.
+
+%%----------------------------------------------------------------------
+%% Auxiliary
+%%----------------------------------------------------------------------
+
+test_mfa(Message, Tag) ->
+ message_receptor ! {Tag, Message}.
+
+message_receptor() ->
+ register(message_receptor, self()),
+ message_receptor([]).
+
+message_receptor(Received) ->
+ receive
+ %% Check if a certain message has been received
+ {check, From, Msg} ->
+ case lists:member(Msg, Received) of
+ true ->
+ From ! {result, true},
+ message_receptor(lists:delete(Msg, Received));
+ false ->
+ From ! {result, Received},
+ message_receptor(Received)
+ end;
+
+ %% Save all other messages
+ Msg ->
+ message_receptor([Msg|Received])
+ end.
diff --git a/lib/parsetools/doc/src/notes.xml b/lib/parsetools/doc/src/notes.xml
index 63c37bc27d..544850308e 100644
--- a/lib/parsetools/doc/src/notes.xml
+++ b/lib/parsetools/doc/src/notes.xml
@@ -30,6 +30,21 @@
</header>
<p>This document describes the changes made to the Parsetools application.</p>
+<section><title>Parsetools 2.0.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Running HiPE-compiled Yecc parsers no longer results
+ in a <c>function_clause</c> error.</p>
+ <p>
+ Own Id: OTP-8771</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Parsetools 2.0.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/parsetools/include/yeccpre.hrl b/lib/parsetools/include/yeccpre.hrl
index 33a103d95f..80a3afbdb6 100644
--- a/lib/parsetools/include/yeccpre.hrl
+++ b/lib/parsetools/include/yeccpre.hrl
@@ -26,8 +26,8 @@
parse(Tokens) ->
yeccpars0(Tokens, {no_func, no_line}, 0, [], []).
--spec parse_and_scan({function() | {atom(), atom()}, [_]} | {atom(), atom(), [_]}) ->
- yecc_ret().
+-spec parse_and_scan({function() | {atom(), atom()}, [_]}
+ | {atom(), atom(), [_]}) -> yecc_ret().
parse_and_scan({F, A}) -> % Fun or {M, F}
yeccpars0([], {{F, A}, no_line}, 0, [], []);
parse_and_scan({M, F, A}) ->
@@ -44,7 +44,7 @@ format_error(Message) ->
%% To be used in grammar files to throw an error message to the parser
%% toplevel. Doesn't have to be exported!
--compile({nowarn_unused_function,{return_error,2}}).
+-compile({nowarn_unused_function, return_error/2}).
-spec return_error(integer(), any()) -> no_return().
return_error(Line, Message) ->
throw({error, {Line, ?MODULE, Message}}).
@@ -57,10 +57,7 @@ yeccpars0(Tokens, Tzr, State, States, Vstack) ->
error: Error ->
Stacktrace = erlang:get_stacktrace(),
try yecc_error_type(Error, Stacktrace) of
- {syntax_error, Token} ->
- yeccerror(Token);
- {missing_in_goto_table=Tag, Symbol, State} ->
- Desc = {Symbol, State, Tag},
+ Desc ->
erlang:raise(error, {yecc_bug, ?CODE_VERSION, Desc},
Stacktrace)
catch _:_ -> erlang:raise(error, Error, Stacktrace)
@@ -70,13 +67,15 @@ yeccpars0(Tokens, Tzr, State, States, Vstack) ->
Error
end.
-yecc_error_type(function_clause, [{?MODULE,F,[State,_,_,_,Token,_,_]} | _]) ->
+yecc_error_type(function_clause, [{?MODULE,F,ArityOrArgs} | _]) ->
case atom_to_list(F) of
- "yeccpars2" ++ _ ->
- {syntax_error, Token};
"yeccgoto_" ++ SymbolL ->
{ok,[{atom,_,Symbol}],_} = erl_scan:string(SymbolL),
- {missing_in_goto_table, Symbol, State}
+ State = case ArityOrArgs of
+ [S,_,_,_,_,_,_] -> S;
+ _ -> state_is_unknown
+ end,
+ {Symbol, State, missing_in_goto_table}
end.
yeccpars1([Token | Tokens], Tzr, State, States, Vstack) ->
@@ -141,11 +140,13 @@ yecctoken_end_location(Token) ->
yecctoken_location(Token)
end.
+-compile({nowarn_unused_function, yeccerror/1}).
yeccerror(Token) ->
Text = yecctoken_to_string(Token),
Location = yecctoken_location(Token),
{error, {Location, ?MODULE, ["syntax error before: ", Text]}}.
+-compile({nowarn_unused_function, yecctoken_to_string/1}).
yecctoken_to_string(Token) ->
case catch erl_scan:token_info(Token, text) of
{text, Txt} -> Txt;
@@ -158,6 +159,7 @@ yecctoken_location(Token) ->
_ -> element(2, Token)
end.
+-compile({nowarn_unused_function, yecctoken2string/1}).
yecctoken2string({atom, _, A}) -> io_lib:write(A);
yecctoken2string({integer,_,N}) -> io_lib:write(N);
yecctoken2string({float,_,F}) -> io_lib:write(F);
@@ -165,7 +167,7 @@ yecctoken2string({char,_,C}) -> io_lib:write_char(C);
yecctoken2string({var,_,V}) -> io_lib:format("~s", [V]);
yecctoken2string({string,_,S}) -> io_lib:write_unicode_string(S);
yecctoken2string({reserved_symbol, _, A}) -> io_lib:write(A);
-yecctoken2string({_Cat, _, Val}) -> io_lib:write(Val);
+yecctoken2string({_Cat, _, Val}) -> io_lib:format("~p",[Val]);
yecctoken2string({dot, _}) -> "'.'";
yecctoken2string({'$end', _}) ->
[];
diff --git a/lib/parsetools/src/yecc.erl b/lib/parsetools/src/yecc.erl
index c4a47d008f..4119e2631b 100644
--- a/lib/parsetools/src/yecc.erl
+++ b/lib/parsetools/src/yecc.erl
@@ -1875,8 +1875,12 @@ format_conflict({Symbol, N, Reduce, Confl}) ->
%% - "__Stack" has been substituted for "Stack";
%% - several states can share yeccpars2_S_cont(), which reduces code size;
%% - instead if calling lists:nthtail() matching code is emitted.
+%%
+%% "1.4", parsetools-2.0.4:
+%% - yeccerror() is called when a syntax error is found (as in version 1.1).
+%% - the include file yeccpre.hrl has been changed.
--define(CODE_VERSION, "1.3").
+-define(CODE_VERSION, "1.4").
-define(YECC_BUG(M, A),
iolist_to_binary([" erlang:error({yecc_bug,\"",?CODE_VERSION,"\",",
io_lib:fwrite(M, A), "}).\n\n"])).
@@ -2106,13 +2110,11 @@ output_call_to_includefile(NewState, St) ->
fwrite(St, <<" yeccpars1(S, ~w, Ss, Stack, T, Ts, Tzr)">>,
[NewState]).
-output_state_actions_fini(State, #yecc{includefile_version = {1,1}}=St0) ->
- %% Backward compatibility.
+output_state_actions_fini(State, St0) ->
+ %% Backward compatible.
St10 = delim(St0, false),
St = fwrite(St10, <<"yeccpars2_~w(_, _, _, _, T, _, _) ->\n">>, [State]),
- fwrite(St, <<" yeccerror(T).\n\n">>, []);
-output_state_actions_fini(_State, St) ->
- fwrite(St, <<".\n\n">>, []).
+ fwrite(St, <<" yeccerror(T).\n\n">>, []).
output_reduce(St0, State, Terminal0,
#reduce{rule_nmbr = RuleNmbr,
@@ -2416,7 +2418,7 @@ include1(Line, Inport, Outport, Nmbr_of_lines) ->
include1(io:get_line(Inport, ''), Inport, Outport, Nmbr_of_lines + Incr).
includefile_version([]) ->
- {1,2};
+ {1,4};
includefile_version(Includefile) ->
case epp:open(Includefile, []) of
{ok, Epp} ->
@@ -2432,7 +2434,7 @@ includefile_version(Includefile) ->
parse_file(Epp) ->
case epp:parse_erl_form(Epp) of
{ok, {function,_Line,yeccpars1,7,_Clauses}} ->
- {1,2};
+ {1,4};
{eof,_Line} ->
{1,1};
_Form ->
diff --git a/lib/parsetools/src/yeccparser.erl b/lib/parsetools/src/yeccparser.erl
index 415547b4ce..63127802ee 100644
--- a/lib/parsetools/src/yeccparser.erl
+++ b/lib/parsetools/src/yeccparser.erl
@@ -38,16 +38,16 @@ line_of(Token) ->
-type yecc_ret() :: {'error', _} | {'ok', _}.
--spec parse(_) -> yecc_ret().
+-spec parse(Tokens :: list()) -> yecc_ret().
parse(Tokens) ->
- yeccpars0(Tokens, false).
+ yeccpars0(Tokens, {no_func, no_line}, 0, [], []).
--spec parse_and_scan({function() | {atom(), atom()}, [_]} | {atom(), atom(), [_]}) ->
- yecc_ret().
+-spec parse_and_scan({function() | {atom(), atom()}, [_]}
+ | {atom(), atom(), [_]}) -> yecc_ret().
parse_and_scan({F, A}) -> % Fun or {M, F}
- yeccpars0([], {F, A});
+ yeccpars0([], {{F, A}, no_line}, 0, [], []);
parse_and_scan({M, F, A}) ->
- yeccpars0([], {{M, F}, A}).
+ yeccpars0([], {{{M, F}, A}, no_line}, 0, [], []).
-spec format_error(any()) -> [char() | list()].
format_error(Message) ->
@@ -60,54 +60,58 @@ format_error(Message) ->
%% To be used in grammar files to throw an error message to the parser
%% toplevel. Doesn't have to be exported!
--compile({nowarn_unused_function,{return_error,2}}).
+-compile({nowarn_unused_function, return_error/2}).
-spec return_error(integer(), any()) -> no_return().
return_error(Line, Message) ->
throw({error, {Line, ?MODULE, Message}}).
--define(CODE_VERSION, "1.3").
+-define(CODE_VERSION, "1.4").
-yeccpars0(Tokens, MFA) ->
- try yeccpars1(Tokens, MFA, 0, [], [])
+yeccpars0(Tokens, Tzr, State, States, Vstack) ->
+ try yeccpars1(Tokens, Tzr, State, States, Vstack)
catch
error: Error ->
Stacktrace = erlang:get_stacktrace(),
try yecc_error_type(Error, Stacktrace) of
- {syntax_error, Token} ->
- yeccerror(Token);
- {missing_in_goto_table=Tag, Symbol, State} ->
- Desc = {Symbol, State, Tag},
+ Desc ->
erlang:raise(error, {yecc_bug, ?CODE_VERSION, Desc},
- Stacktrace)
+ Stacktrace)
catch _:_ -> erlang:raise(error, Error, Stacktrace)
end;
- throw: {error, {_Line, ?MODULE, _M}} = Error ->
- Error % probably from return_error/2
+ %% Probably thrown from return_error/2:
+ throw: {error, {_Line, ?MODULE, _M}} = Error ->
+ Error
end.
-yecc_error_type(function_clause, [{?MODULE,F,[State,_,_,_,Token,_,_]} | _]) ->
+yecc_error_type(function_clause, [{?MODULE,F,ArityOrArgs} | _]) ->
case atom_to_list(F) of
- "yeccpars2" ++ _ ->
- {syntax_error, Token};
"yeccgoto_" ++ SymbolL ->
{ok,[{atom,_,Symbol}],_} = erl_scan:string(SymbolL),
- {missing_in_goto_table, Symbol, State}
+ State = case ArityOrArgs of
+ [S,_,_,_,_,_,_] -> S;
+ _ -> state_is_unknown
+ end,
+ {Symbol, State, missing_in_goto_table}
end.
-yeccpars1([Token | Tokens], Tokenizer, State, States, Vstack) ->
- yeccpars2(State, element(1, Token), States, Vstack, Token, Tokens,
- Tokenizer);
-yeccpars1([], {F, A}, State, States, Vstack) ->
+yeccpars1([Token | Tokens], Tzr, State, States, Vstack) ->
+ yeccpars2(State, element(1, Token), States, Vstack, Token, Tokens, Tzr);
+yeccpars1([], {{F, A},_Line}, State, States, Vstack) ->
case apply(F, A) of
- {ok, Tokens, _Endline} ->
- yeccpars1(Tokens, {F, A}, State, States, Vstack);
- {eof, _Endline} ->
- yeccpars1([], false, State, States, Vstack);
+ {ok, Tokens, Endline} ->
+ yeccpars1(Tokens, {{F, A}, Endline}, State, States, Vstack);
+ {eof, Endline} ->
+ yeccpars1([], {no_func, Endline}, State, States, Vstack);
{error, Descriptor, _Endline} ->
{error, Descriptor}
end;
-yeccpars1([], false, State, States, Vstack) ->
- yeccpars2(State, '$end', States, Vstack, {'$end', 999999}, [], false).
+yeccpars1([], {no_func, no_line}, State, States, Vstack) ->
+ Line = 999999,
+ yeccpars2(State, '$end', States, Vstack, yecc_end(Line), [],
+ {no_func, Line});
+yeccpars1([], {no_func, Endline}, State, States, Vstack) ->
+ yeccpars2(State, '$end', States, Vstack, yecc_end(Endline), [],
+ {no_func, Endline}).
%% yeccpars1/7 is called from generated code.
%%
@@ -115,48 +119,73 @@ yeccpars1([], false, State, States, Vstack) ->
%% yeccpars1/7 can be found by parsing the file without following
%% include directives. yecc will otherwise assume that an old
%% yeccpre.hrl is included (one which defines yeccpars1/5).
-yeccpars1(State1, State, States, Vstack, Stack1, [Token | Tokens],
- Tokenizer) ->
+yeccpars1(State1, State, States, Vstack, Token0, [Token | Tokens], Tzr) ->
yeccpars2(State, element(1, Token), [State1 | States],
- [Stack1 | Vstack], Token, Tokens, Tokenizer);
-yeccpars1(State1, State, States, Vstack, Stack1, [], {F, A}) ->
- case apply(F, A) of
- {ok, Tokens, _Endline} ->
- yeccpars1(State1, State, States, Vstack, Stack1, Tokens, {F, A});
- {eof, _Endline} ->
- yeccpars1(State1, State, States, Vstack, Stack1, [], false);
- {error, Descriptor, _Endline} ->
- {error, Descriptor}
- end;
-yeccpars1(State1, State, States, Vstack, Stack1, [], false) ->
- yeccpars2(State, '$end', [State1 | States], [Stack1 | Vstack],
- {'$end', 999999}, [], false).
+ [Token0 | Vstack], Token, Tokens, Tzr);
+yeccpars1(State1, State, States, Vstack, Token0, [], {{_F,_A}, _Line}=Tzr) ->
+ yeccpars1([], Tzr, State, [State1 | States], [Token0 | Vstack]);
+yeccpars1(State1, State, States, Vstack, Token0, [], {no_func, no_line}) ->
+ Line = yecctoken_end_location(Token0),
+ yeccpars2(State, '$end', [State1 | States], [Token0 | Vstack],
+ yecc_end(Line), [], {no_func, Line});
+yeccpars1(State1, State, States, Vstack, Token0, [], {no_func, Line}) ->
+ yeccpars2(State, '$end', [State1 | States], [Token0 | Vstack],
+ yecc_end(Line), [], {no_func, Line}).
+
+%% For internal use only.
+yecc_end({Line,_Column}) ->
+ {'$end', Line};
+yecc_end(Line) ->
+ {'$end', Line}.
+
+yecctoken_end_location(Token) ->
+ try
+ {text, Str} = erl_scan:token_info(Token, text),
+ {line, Line} = erl_scan:token_info(Token, line),
+ Parts = re:split(Str, "\n"),
+ Dline = length(Parts) - 1,
+ Yline = Line + Dline,
+ case erl_scan:token_info(Token, column) of
+ {column, Column} ->
+ Col = byte_size(lists:last(Parts)),
+ {Yline, Col + if Dline =:= 0 -> Column; true -> 1 end};
+ undefined ->
+ Yline
+ end
+ catch _:_ ->
+ yecctoken_location(Token)
+ end.
-% For internal use only.
yeccerror(Token) ->
- Text = case catch erl_scan:token_info(Token, text) of
- {text, Txt} -> Txt;
- _ -> yecctoken2string(Token)
- end,
- Location = case catch erl_scan:token_info(Token, location) of
- {location, Loc} -> Loc;
- _ -> element(2, Token)
- end,
+ Text = yecctoken_to_string(Token),
+ Location = yecctoken_location(Token),
{error, {Location, ?MODULE, ["syntax error before: ", Text]}}.
+yecctoken_to_string(Token) ->
+ case catch erl_scan:token_info(Token, text) of
+ {text, Txt} -> Txt;
+ _ -> yecctoken2string(Token)
+ end.
+
+yecctoken_location(Token) ->
+ case catch erl_scan:token_info(Token, location) of
+ {location, Loc} -> Loc;
+ _ -> element(2, Token)
+ end.
+
yecctoken2string({atom, _, A}) -> io_lib:write(A);
yecctoken2string({integer,_,N}) -> io_lib:write(N);
yecctoken2string({float,_,F}) -> io_lib:write(F);
yecctoken2string({char,_,C}) -> io_lib:write_char(C);
yecctoken2string({var,_,V}) -> io_lib:format("~s", [V]);
yecctoken2string({string,_,S}) -> io_lib:write_unicode_string(S);
-yecctoken2string({reserved_symbol, _, A}) -> io_lib:format("~w", [A]);
-yecctoken2string({_Cat, _, Val}) -> io_lib:format("~w", [Val]);
+yecctoken2string({reserved_symbol, _, A}) -> io_lib:write(A);
+yecctoken2string({_Cat, _, Val}) -> io_lib:write(Val);
yecctoken2string({dot, _}) -> "'.'";
yecctoken2string({'$end', _}) ->
[];
yecctoken2string({Other, _}) when is_atom(Other) ->
- io_lib:format("~w", [Other]);
+ io_lib:write(Other);
yecctoken2string(Other) ->
io_lib:write(Other).
@@ -164,7 +193,7 @@ yecctoken2string(Other) ->
--file("yeccparser.erl", 168).
+-file("yeccparser.erl", 196).
yeccpars2(0=S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_0(S, Cat, Ss, Stack, T, Ts, Tzr);
@@ -248,7 +277,9 @@ yeccpars2_0(S, integer, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_0(S, reserved_word, Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 8, Ss, Stack, T, Ts, Tzr);
yeccpars2_0(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 9, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 9, Ss, Stack, T, Ts, Tzr);
+yeccpars2_0(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_1(S, atom, Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 6, Ss, Stack, T, Ts, Tzr);
@@ -267,10 +298,14 @@ yeccpars2_2(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_grammar(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_3(S, '->', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 10, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 10, Ss, Stack, T, Ts, Tzr);
+yeccpars2_3(_, _, _, _, T, _, _) ->
+ yeccerror(T).
-yeccpars2_4(_S, '$end', _Ss, Stack, _T, _Ts, _Tzr) ->
- {ok, hd(Stack)}.
+yeccpars2_4(_S, '$end', _Ss, Stack, _T, _Ts, _Tzr) ->
+ {ok, hd(Stack)};
+yeccpars2_4(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_5(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_grammar(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
@@ -317,7 +352,9 @@ yeccpars2_13(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_symbols(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_14(S, dot, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 29, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 29, Ss, Stack, T, Ts, Tzr);
+yeccpars2_14(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_15(S, '->', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 18, Ss, Stack, T, Ts, Tzr);
@@ -338,7 +375,9 @@ yeccpars2_15(S, reserved_word, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_15(S, string, Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 26, Ss, Stack, T, Ts, Tzr);
yeccpars2_15(S, var, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 27, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 27, Ss, Stack, T, Ts, Tzr);
+yeccpars2_15(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_|Nss] = Ss,
@@ -414,10 +453,14 @@ yeccpars2_29(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_rule(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_30(S, dot, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 35, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 35, Ss, Stack, T, Ts, Tzr);
+yeccpars2_30(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_31(S, dot, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 34, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 34, Ss, Stack, T, Ts, Tzr);
+yeccpars2_31(_, _, _, _, T, _, _) ->
+ yeccerror(T).
yeccpars2_32(S, string, Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 32, Ss, Stack, T, Ts, Tzr);
@@ -486,7 +529,7 @@ yeccgoto_tokens(15=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_tokens(17=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_28(_S, Cat, Ss, Stack, T, Ts, Tzr).
--compile({inline,{yeccpars2_6_,1}}).
+-compile({inline,yeccpars2_6_/1}).
-file("yeccgramm.yrl", 44).
yeccpars2_6_(__Stack0) ->
[__1 | __Stack] = __Stack0,
@@ -494,7 +537,7 @@ yeccpars2_6_(__Stack0) ->
symbol ( __1 )
end | __Stack].
--compile({inline,{yeccpars2_7_,1}}).
+-compile({inline,yeccpars2_7_/1}).
-file("yeccgramm.yrl", 45).
yeccpars2_7_(__Stack0) ->
[__1 | __Stack] = __Stack0,
@@ -502,7 +545,7 @@ yeccpars2_7_(__Stack0) ->
symbol ( __1 )
end | __Stack].
--compile({inline,{yeccpars2_8_,1}}).
+-compile({inline,yeccpars2_8_/1}).
-file("yeccgramm.yrl", 46).
yeccpars2_8_(__Stack0) ->
[__1 | __Stack] = __Stack0,
@@ -510,7 +553,7 @@ yeccpars2_8_(__Stack0) ->
symbol ( __1 )
end | __Stack].
--compile({inline,{yeccpars2_9_,1}}).
+-compile({inline,yeccpars2_9_/1}).
-file("yeccgramm.yrl", 43).
yeccpars2_9_(__Stack0) ->
[__1 | __Stack] = __Stack0,
@@ -518,14 +561,14 @@ yeccpars2_9_(__Stack0) ->
symbol ( __1 )
end | __Stack].
--compile({inline,{yeccpars2_11_,1}}).
+-compile({inline,yeccpars2_11_/1}).
-file("yeccgramm.yrl", 40).
yeccpars2_11_(__Stack0) ->
[begin
{ erlang_code , [ { atom , 0 , '$undefined' } ] }
end | __Stack0].
--compile({inline,{yeccpars2_12_,1}}).
+-compile({inline,yeccpars2_12_/1}).
-file("yeccgramm.yrl", 35).
yeccpars2_12_(__Stack0) ->
[__1 | __Stack] = __Stack0,
@@ -533,7 +576,7 @@ yeccpars2_12_(__Stack0) ->
[ __1 ]
end | __Stack].
--compile({inline,{yeccpars2_13_,1}}).
+-compile({inline,yeccpars2_13_/1}).
-file("yeccgramm.yrl", 36).
yeccpars2_13_(__Stack0) ->
[__2,__1 | __Stack] = __Stack0,
@@ -541,7 +584,7 @@ yeccpars2_13_(__Stack0) ->
[ __1 | __2 ]
end | __Stack].
--compile({inline,{yeccpars2_16_,1}}).
+-compile({inline,yeccpars2_16_/1}).
-file("yeccgramm.yrl", 39).
yeccpars2_16_(__Stack0) ->
[__2,__1 | __Stack] = __Stack0,
@@ -549,7 +592,7 @@ yeccpars2_16_(__Stack0) ->
{ erlang_code , __2 }
end | __Stack].
--compile({inline,{yeccpars2_17_,1}}).
+-compile({inline,yeccpars2_17_/1}).
-file("yeccgramm.yrl", 41).
yeccpars2_17_(__Stack0) ->
[__1 | __Stack] = __Stack0,
@@ -557,7 +600,7 @@ yeccpars2_17_(__Stack0) ->
[ __1 ]
end | __Stack].
--compile({inline,{yeccpars2_18_,1}}).
+-compile({inline,yeccpars2_18_/1}).
-file("yeccgramm.yrl", 55).
yeccpars2_18_(__Stack0) ->
[__1 | __Stack] = __Stack0,
@@ -565,7 +608,7 @@ yeccpars2_18_(__Stack0) ->
{ '->' , line_of ( __1 ) }
end | __Stack].
--compile({inline,{yeccpars2_19_,1}}).
+-compile({inline,yeccpars2_19_/1}).
-file("yeccgramm.yrl", 56).
yeccpars2_19_(__Stack0) ->
[__1 | __Stack] = __Stack0,
@@ -573,7 +616,7 @@ yeccpars2_19_(__Stack0) ->
{ ':' , line_of ( __1 ) }
end | __Stack].
--compile({inline,{yeccpars2_24_,1}}).
+-compile({inline,yeccpars2_24_/1}).
-file("yeccgramm.yrl", 53).
yeccpars2_24_(__Stack0) ->
[__1 | __Stack] = __Stack0,
@@ -581,7 +624,7 @@ yeccpars2_24_(__Stack0) ->
{ value_of ( __1 ) , line_of ( __1 ) }
end | __Stack].
--compile({inline,{yeccpars2_25_,1}}).
+-compile({inline,yeccpars2_25_/1}).
-file("yeccgramm.yrl", 54).
yeccpars2_25_(__Stack0) ->
[__1 | __Stack] = __Stack0,
@@ -589,7 +632,7 @@ yeccpars2_25_(__Stack0) ->
{ value_of ( __1 ) , line_of ( __1 ) }
end | __Stack].
--compile({inline,{yeccpars2_28_,1}}).
+-compile({inline,yeccpars2_28_/1}).
-file("yeccgramm.yrl", 42).
yeccpars2_28_(__Stack0) ->
[__2,__1 | __Stack] = __Stack0,
@@ -597,7 +640,7 @@ yeccpars2_28_(__Stack0) ->
[ __1 | __2 ]
end | __Stack].
--compile({inline,{yeccpars2_29_,1}}).
+-compile({inline,yeccpars2_29_/1}).
-file("yeccgramm.yrl", 33).
yeccpars2_29_(__Stack0) ->
[__5,__4,__3,__2,__1 | __Stack] = __Stack0,
@@ -605,7 +648,7 @@ yeccpars2_29_(__Stack0) ->
{ rule , [ __1 | __3 ] , __4 }
end | __Stack].
--compile({inline,{yeccpars2_32_,1}}).
+-compile({inline,yeccpars2_32_/1}).
-file("yeccgramm.yrl", 37).
yeccpars2_32_(__Stack0) ->
[__1 | __Stack] = __Stack0,
@@ -613,7 +656,7 @@ yeccpars2_32_(__Stack0) ->
[ __1 ]
end | __Stack].
--compile({inline,{yeccpars2_33_,1}}).
+-compile({inline,yeccpars2_33_/1}).
-file("yeccgramm.yrl", 38).
yeccpars2_33_(__Stack0) ->
[__2,__1 | __Stack] = __Stack0,
@@ -621,7 +664,7 @@ yeccpars2_33_(__Stack0) ->
[ __1 | __2 ]
end | __Stack].
--compile({inline,{yeccpars2_34_,1}}).
+-compile({inline,yeccpars2_34_/1}).
-file("yeccgramm.yrl", 32).
yeccpars2_34_(__Stack0) ->
[__3,__2,__1 | __Stack] = __Stack0,
@@ -629,7 +672,7 @@ yeccpars2_34_(__Stack0) ->
{ __1 , __2 }
end | __Stack].
--compile({inline,{yeccpars2_35_,1}}).
+-compile({inline,yeccpars2_35_/1}).
-file("yeccgramm.yrl", 31).
yeccpars2_35_(__Stack0) ->
[__3,__2,__1 | __Stack] = __Stack0,
diff --git a/lib/parsetools/test/yecc_SUITE.erl b/lib/parsetools/test/yecc_SUITE.erl
index 61e2456323..8153be7e61 100644
--- a/lib/parsetools/test/yecc_SUITE.erl
+++ b/lib/parsetools/test/yecc_SUITE.erl
@@ -46,7 +46,7 @@
bugs/1,
otp_5369/1, otp_6362/1, otp_7945/1, otp_8483/1, otp_8486/1,
improvements/1,
- otp_7292/1, otp_7969/1]).
+ otp_7292/1, otp_7969/1, otp_8919/1]).
% Default timetrap timeout (set in init_per_testcase).
-define(default_timeout, ?t:minutes(1)).
@@ -298,8 +298,8 @@ syntax(Config) when is_list(Config) ->
{_,[{L1,_,{undefined_function,{yeccpars2_2_,1}}},
{L2,_,{bad_inline,{yeccpars2_2_,1}}}]}],
[]} = compile:file(Parserfile1, [basic_validation,return]),
- ?line L1 = 24 + SzYeccPre,
- ?line L2 = 31 + SzYeccPre
+ ?line L1 = 28 + SzYeccPre,
+ ?line L2 = 35 + SzYeccPre
end(),
%% Bad macro in action. OTP-7224.
@@ -316,8 +316,8 @@ syntax(Config) when is_list(Config) ->
{_,[{L1,_,{undefined_function,{yeccpars2_2_,1}}},
{L2,_,{bad_inline,{yeccpars2_2_,1}}}]}],
[]} = compile:file(Parserfile1, [basic_validation,return]),
- ?line L1 = 24 + SzYeccPre,
- ?line L2 = 31 + SzYeccPre
+ ?line L1 = 28 + SzYeccPre,
+ ?line L2 = 35 + SzYeccPre
end(),
%% Check line numbers. OTP-7224.
@@ -1541,7 +1541,7 @@ otp_8486(Config) when is_list(Config) ->
ok.
improvements(suite) ->
- [otp_7292, otp_7969].
+ [otp_7292, otp_7969, otp_8919].
otp_7292(doc) ->
"OTP-7292. Header declarations for edoc.";
@@ -1584,8 +1584,8 @@ otp_7292(Config) when is_list(Config) ->
{L2,_,{bad_inline,{yeccpars2_2_,1}}}]}],
[{_,[{16,_,{unused_function,{foo,0}}}]}]} =
compile:file(Parserfile1, [basic_validation, return]),
- ?line L1 = 34 + SzYeccPre,
- ?line L2 = 41 + SzYeccPre
+ ?line L1 = 38 + SzYeccPre,
+ ?line L2 = 45 + SzYeccPre
end(),
YeccPre = filename:join(Dir, "yeccpre.hrl"),
@@ -1602,8 +1602,8 @@ otp_7292(Config) when is_list(Config) ->
{L2,_,{bad_inline,{yeccpars2_2_,1}}}]}],
[{_,[{16,_,{unused_function,{foo,0}}}]}]} =
compile:file(Parserfile1, [basic_validation, return]),
- ?line L1 = 33 + SzYeccPre,
- ?line L2 = 40 + SzYeccPre
+ ?line L1 = 37 + SzYeccPre,
+ ?line L2 = 44 + SzYeccPre
end(),
file:delete(YeccPre),
@@ -1773,6 +1773,14 @@ otp_7969(Config) when is_list(Config) ->
?line {error,{{1,11},erl_parse,_}} = erl_parse:parse_and_scan({F6, []}),
ok.
+otp_8919(doc) ->
+ "OTP-8919. Improve formating of Yecc error messages.";
+otp_8919(suite) -> [];
+otp_8919(Config) when is_list(Config) ->
+ {error,{1,Mod,Mess}} = erl_parse:parse([{cat,1,"hello"}]),
+ "syntax error before: \"hello\"" = lists:flatten(Mod:format_error(Mess)),
+ ok.
+
yeccpre_size() ->
yeccpre_size(default_yeccpre()).
diff --git a/lib/parsetools/vsn.mk b/lib/parsetools/vsn.mk
index f3e2dc0fb4..46915baed6 100644
--- a/lib/parsetools/vsn.mk
+++ b/lib/parsetools/vsn.mk
@@ -1 +1 @@
-PARSETOOLS_VSN = 2.0.3
+PARSETOOLS_VSN = 2.0.4
diff --git a/lib/public_key/asn1/OTP-PKIX.asn1 b/lib/public_key/asn1/OTP-PKIX.asn1
index c0cf440496..ad704191a9 100644
--- a/lib/public_key/asn1/OTP-PKIX.asn1
+++ b/lib/public_key/asn1/OTP-PKIX.asn1
@@ -302,18 +302,25 @@ SupportedPublicKeyAlgorithms PUBLIC-KEY-ALGORITHM-CLASS ::= {
-- DSA Keys and Signatures
+
+ DSAParams ::= CHOICE
+ {
+ params Dss-Parms,
+ null NULL
+ }
+
-- SubjectPublicKeyInfo:
dsa PUBLIC-KEY-ALGORITHM-CLASS ::= {
ID id-dsa
- TYPE Dss-Parms -- XXX Must be OPTIONAL
+ TYPE DSAParams -- XXX Must be OPTIONAL
PUBLIC-KEY-TYPE DSAPublicKey }
-- Certificate.signatureAlgorithm
dsa-with-sha1 SIGNATURE-ALGORITHM-CLASS ::= {
- ID id-dsa-with-sha1
- TYPE Dss-Parms }
+ ID id-dsa-with-sha1
+ TYPE DSAParams }
--
-- RSA Keys and Signatures
diff --git a/lib/public_key/doc/src/cert_records.xml b/lib/public_key/doc/src/cert_records.xml
index 8cfe57f670..0d6113acef 100644
--- a/lib/public_key/doc/src/cert_records.xml
+++ b/lib/public_key/doc/src/cert_records.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE chapter SYSTEM "chapter.dtd">
<chapter>
@@ -37,7 +37,7 @@
<p>This chapter briefly describes erlang records derived from asn1
specifications used to handle X509 certificates. The intent is to
describe the data types and not to specify the meaning of each
- component for this we refer you to RFC 3280.
+ component for this we refer you to RFC 5280.
</p>
<p>Use the following include directive to get access to the
@@ -45,11 +45,7 @@
<code> -include_lib("public_key/include/public_key.hrl"). </code>
- <p>The used specification is available in <c>OTP-PKIX.asn1</c>,
- which is an amelioration of
- the <c>PKIX1Explicit88.asn1</c>, <c>PKIX1Implicit88.asn1</c>
- and <c>PKIX1Algorithms88.asn1</c> modules.
- You find all these modules in the <c>asn1</c> subdirectory
+ <p>The used asn1 specifications are available <c>asn1</c> subdirectory
of the application <c>public_key</c>.
</p>
@@ -62,6 +58,9 @@
marker="public_key">public key reference manual </seealso> or
follows here.</p>
+ <p><c>oid() - a tuple of integers
+ as generated by the asn1 compiler.</c></p>
+
<p><c>time() = uct_time() | general_time()</c></p>
<p><c>uct_time() = {utcTime, "YYMMDDHHMMSSZ"} </c></p>
@@ -119,9 +118,31 @@
algorithm, % oid()
parameters % asn1_der_encoded()
}.
+</code>
+
+<code>
+#'OTPCertificate'{
+ tbsCertificate, % #'OTPTBSCertificate'{}
+ signatureAlgorithm, % #'SignatureAlgorithm'
+ signature % {0, binary()} - asn1 compact bitstring
+ }.
+
+#'OTPTBSCertificate'{
+ version, % v1 | v2 | v3
+ serialNumber, % integer()
+ signature, % #'SignatureAlgorithm'
+ issuer, % {rdnSequence, [#AttributeTypeAndValue'{}]}
+ validity, % #'Validity'{}
+ subject, % {rdnSequence, [#AttributeTypeAndValue'{}]}
+ subjectPublicKeyInfo, % #'SubjectPublicKeyInfo'{}
+ issuerUniqueID, % binary() | asn1_novalue
+ subjectUniqueID, % binary() | asn1_novalue
+ extensions % [#'Extension'{}]
+ }.
+
#'SignatureAlgorithm'{
algorithm, % id_signature_algorithm()
- parameters % public_key_params()
+ parameters % asn1_novalue | #'Dss-Parms'{}
}.
</code>
diff --git a/lib/public_key/doc/src/notes.xml b/lib/public_key/doc/src/notes.xml
index 13a9151869..6e7381eb18 100644
--- a/lib/public_key/doc/src/notes.xml
+++ b/lib/public_key/doc/src/notes.xml
@@ -1,11 +1,11 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE chapter SYSTEM "chapter.dtd">
<chapter>
<header>
<copyright>
<year>2008</year>
- <year>2008</year>
+ <year>2010</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -34,6 +34,96 @@
<file>notes.xml</file>
</header>
+<section><title>Public_Key 0.9</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Updated ssl to ignore CA certs that violate the asn1-spec
+ for a certificate, and updated public key asn1 spec to
+ handle inherited DSS-params.</p>
+ <p>
+ Own Id: OTP-7884</p>
+ </item>
+ <item>
+ <p>
+ Changed ssl implementation to retain backwards
+ compatibility for old option {verify, 0} that shall be
+ equivalent to {verify, verify_none}, also separate the
+ cases unknown ca and selfsigned peer cert, and restored
+ return value of deprecated function
+ public_key:pem_to_der/1.</p>
+ <p>
+ Own Id: OTP-8858</p>
+ </item>
+ <item>
+ <p>
+ Better handling of v1 and v2 certificates. V1 and v2
+ certificates does not have any extensions so then
+ validate_extensions should just accept that there are
+ none and not end up in missing_basic_constraints clause.</p>
+ <p>
+ Own Id: OTP-8867</p>
+ </item>
+ <item>
+ <p>
+ Changed the verify fun so that it differentiate between
+ the peer certificate and CA certificates by using
+ valid_peer or valid as the second argument to the verify
+ fun. It may not always be trivial or even possible to
+ know when the peer certificate is reached otherwise.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-8873</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Public_Key 0.8</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Handling of unknown CA certificates was changed in ssl
+ and public_key to work as intended.</p>
+ <p>
+ Own Id: OTP-8788</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Revise the public_key API - Cleaned up and documented the
+ public_key API to make it useful for general use, also
+ changed ssl to use the new API.</p>
+ <p>
+ Own Id: OTP-8722</p>
+ </item>
+ <item>
+ <p>
+ Added the functionality so that the verification fun will
+ be called when a certificate is considered valid by the
+ path validation to allow access to each certificate in
+ the path to the user application. Also try to verify
+ subject-AltName, if unable to verify it let the
+ application verify it.</p>
+ <p>
+ Own Id: OTP-8825</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Public_Key 0.7</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml
index dc9a96906f..c72719fac4 100644
--- a/lib/public_key/doc/src/public_key.xml
+++ b/lib/public_key/doc/src/public_key.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE erlref SYSTEM "erlref.dtd">
<erlref>
@@ -34,11 +34,7 @@
<modulesummary> API module for public key infrastructure.</modulesummary>
<description>
<p>This module provides functions to handle public key infrastructure
- from RFC 3280 - X.509 certificates (will later be upgraded to RFC 5280)
- and some parts of the PKCS-standard.
- Currently this application is mainly used by the new
- ssl implementation. The API is yet under construction
- and only a few of the functions are currently documented and thereby supported.
+ from RFC 5280 - X.509 certificates and some parts of the PKCS-standard.
</p>
</description>
@@ -62,37 +58,37 @@
<p><c>boolean() = true | false</c></p>
- <p><c>string = [bytes()]</c></p>
-
- <p><c>asn1_der_encoded() = binary() | [bytes()]</c></p>
+ <p><c>string = [bytes()]</c></p>
+
+ <p><c>der_encoded() = binary() </c></p>
- <p><c>der_bin() = binary() </c></p>
+ <p><c>decrypt_der() = binary() </c></p>
- <p><c>oid() - a tuple of integers
- as generated by the asn1 compiler.</c></p>
-
- <p><c>public_key() = rsa_public_key() | dsa_public_key()</c></p>
+ <p><c>pki_asn1_type() = 'Certificate' | 'RSAPrivateKey'|
+ 'DSAPrivateKey' | 'DHParameter'</c></p>
+ <p><c>pem_entry () = {pki_asn1_type(), der_encoded() | decrypt_der(), not_encrypted |
+ {"DES-CBC" | "DES-EDE3-CBC", crypto:rand_bytes(8)}}.</c></p>
+
<p><c>rsa_public_key() = #'RSAPublicKey'{}</c></p>
<p><c>rsa_private_key() = #'RSAPrivateKey'{} </c></p>
- <p><c>dsa_public_key() = integer() </c></p>
-
- <p><c>public_key_params() = dsa_key_params() </c></p>
-
- <p><c>dsa_key_params() = #'Dss-Parms'{} </c></p>
-
- <p><c>private_key() = rsa_private_key() | dsa_private_key()</c></p>
+ <p><c>dsa_public_key() = {integer(), #'Dss-Parms'{}} </c></p>
<p><c>rsa_private_key() = #'RSAPrivateKey'{} </c></p>
<p><c>dsa_private_key() = #'DSAPrivateKey'{}</c></p>
+
+ <p><c> public_crypt_options() = [{rsa_pad, rsa_padding()}]. </c></p>
- <p><c>x509_certificate() = "#Certificate{}"</c></p>
-
- <p><c>x509_tbs_certificate() = #'TBSCertificate'{} </c></p>
-
+ <p><c> rsa_padding() = 'rsa_pkcs1_padding' | 'rsa_pkcs1_oaep_padding'
+ | 'rsa_no_padding'</c></p>
+
+ <p><c> rsa_digest_type() = 'md5' | 'sha' </c></p>
+
+ <p><c> dss_digest_type() = 'none' | 'sha' </c></p>
+
<!-- <p><c>policy_tree() = [Root, Children]</c></p> -->
<!-- <p><c>Root = #policy_tree_node{}</c></p> -->
@@ -121,197 +117,301 @@
<!-- that would satisfy this policy in the certificate x+1. </item> -->
<!-- </taglist> -->
</section>
-
-<funcs>
- <func>
- <name>decode_private_key(KeyInfo) -> </name>
- <name>decode_private_key(KeyInfo, Password) -> {ok, PrivateKey} | {error, Reason}</name>
- <fsummary> Decodes an asn1 der encoded private key.</fsummary>
- <type>
- <v> KeyInfo = {KeyType, der_bin(), ChipherInfo} </v>
- <d> As returned from pem_to_der/1 for private keys</d>
- <v> KeyType = rsa_private_key | dsa_private_key </v>
- <v> ChipherInfo = opaque() | no_encryption </v>
- <d> ChipherInfo may contain encryption parameters if the private key is password
- protected, these are opaque to the user just pass the value returned by pem_to_der/1
- to this function.</d>
- <v> Password = string() </v>
- <d>Must be specified if CipherInfo =/= no_encryption</d>
- <v> PrivateKey = private_key() </v>
- <v> Reason = term() </v>
- </type>
- <desc>
- <p>Decodes an asn1 der encoded private key.</p>
- </desc>
- </func>
-
+
+<funcs>
+
<func>
- <name>pem_to_der(File) -> {ok, [Entry]}</name>
- <fsummary>Reads a PEM file and translates it into its asn1 der
- encoded parts.</fsummary>
+ <name>decrypt_private(CipherText, Key [, Options]) -> binary()</name>
+ <fsummary>Public key decryption.</fsummary>
<type>
- <v>File = path()</v>
- <v>Password = string()</v>
- <v>Entry = {entry_type(), der_bin(), CipherInfo}</v>
- <v> ChipherInfo = opaque() | no_encryption </v>
- <d> ChipherInfo may contain encryption parameters if the private key is password
- protected, these will be handled by the function decode_private_key/2. </d>
- <v>entry_type() = cert | cert_req | rsa_private_key | dsa_private_key |
- dh_params </v>
+ <v>CipherText = binary()</v>
+ <v>Key = rsa_private_key()</v>
+ <v>Options = public_crypt_options()</v>
</type>
<desc>
- <p>Reads a PEM file and translates it into its asn1 der
- encoded parts.</p>
+ <p>Public key decryption using the private key.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>decrypt_public(CipherText, Key [, Options]) - > binary()</name>
+ <fsummary></fsummary>
+ <type>
+ <v>CipherText = binary()</v>
+ <v>Key = rsa_public_key()</v>
+ <v>Options = public_crypt_options()</v>
+ </type>
+ <desc>
+ <p> Public key decryption using the public key.</p>
</desc>
</func>
-
- <func>
- <name>pkix_decode_cert(Cert, Type) -> {ok, DecodedCert} | {error, Reason}</name>
- <fsummary> Decodes an asn1 der encoded pkix certificate. </fsummary>
- <type>
- <v>Cert = asn1_der_encoded() </v>
- <v>Type = plain | otp</v>
- <v>DecodeCert = x509_certificate() </v>
- <d>When type is specified as otp the asn1 spec OTP-PKIX.asn1 is used to decode known
- extensions and enhance the signature field in
- #'Certificate'{} and '#TBSCertificate'{}. This is currently used by the new ssl
- implementation but not documented and supported for the public_key application.</d>
- <v>Reason = term() </v>
+
+ <func>
+ <name>der_decode(Asn1type, Der) -> term()</name>
+ <fsummary> Decodes a public key asn1 der encoded entity.</fsummary>
+ <type>
+ <v>Asn1Type = atom() -</v>
+ <d> Asn1 type present in the public_key applications
+ asn1 specifications.</d>
+ <v>Der = der_encoded()</v>
</type>
- <desc>
- <p> Decodes an asn1 encoded pkix certificate.</p>
+ <desc>
+ <p> Decodes a public key asn1 der encoded entity.</p>
</desc>
</func>
+
+ <func>
+ <name>der_encode(Asn1Type, Entity) -> der_encoded()</name>
+ <fsummary> Encodes a public key entity with asn1 DER encoding.</fsummary>
+ <type>
+ <v>Asn1Type = atom()</v>
+ <d> Asn1 type present in the public_key applications
+ asn1 specifications.</d>
+ <v>Entity = term() - The erlang representation of <c> Asn1Type</c></v>
+ </type>
+ <desc>
+ <p> Encodes a public key entity with asn1 DER encoding.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>pem_decode(PemBin) -> [pem_entry()]</name>
+ <fsummary>Decode PEM binary data and return
+ entries as asn1 der encoded entities. </fsummary>
+ <type>
+ <v>PemBin = binary()</v>
+ <d>Example {ok, PemBin} = file:read_file("cert.pem").</d>
+ </type>
+ <desc>
+ <p>Decode PEM binary data and return
+ entries as asn1 der encoded entities.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>pem_encode(PemEntries) -> binary()</name>
+ <fsummary>Creates a PEM binary</fsummary>
+ <type>
+ <v> PemEntries = [pem_entry()] </v>
+ </type>
+ <desc>
+ <p>Creates a PEM binary</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>pem_entry_decode(PemEntry [, Password]) -> term()</name>
+ <fsummary>Decodes a pem entry.</fsummary>
+ <type>
+ <v> PemEntry = pem_entry() </v>
+ <v> Password = string() </v>
+ </type>
+ <desc>
+ <p>Decodes a pem entry. pem_decode/1 returns a list of
+ pem entries.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>pem_entry_encode(Asn1Type, Entity [,{CipherInfo, Password}]) -> pem_entry()</name>
+ <fsummary> Creates a pem entry that can be feed to pem_encode/1.</fsummary>
+ <type>
+ <v>Asn1Type = atom()</v>
+ <v>Entity = term()</v>
+ <v>CipherInfo = {"DES-CBC" | "DES-EDE3-CBC", crypto:rand_bytes(8)}</v>
+ <v>Password = string()</v>
+ </type>
+ <desc>
+ <p> Creates a pem entry that can be feed to pem_encode/1.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>encrypt_private(PlainText, Key) -> binary()</name>
+ <fsummary> Public key encryption using the private key.</fsummary>
+ <type>
+ <v>PlainText = binary()</v>
+ <v>Key = rsa_private_key()</v>
+ </type>
+ <desc>
+ <p> Public key encryption using the private key.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>encrypt_public(PlainText, Key) -> binary()</name>
+ <fsummary> Public key encryption using the public key.</fsummary>
+ <type>
+ <v>PlainText = binary()</v>
+ <v>Key = rsa_public_key()</v>
+ </type>
+ <desc>
+ <p> Public key encryption using the public key.</p>
+ </desc>
+ </func>
-<!-- <func> -->
-<!-- <name> pkix_encode_cert(Cert) -> {ok, EncodedCert} | {error, Reason}</name> -->
-<!-- <fsummary>Encodes a certificate record using asn1. </fsummary> -->
-<!-- <type> -->
-<!-- <v>Cert = x509_certificate() </v> -->
-<!-- <v>EncodedCert = asn1_der_encoded() </v> -->
-<!-- <v>Reason = term() </v> -->
-<!-- </type> -->
-<!-- <desc> -->
-<!-- <p> Encodes a certificate record using asn1.</p> -->
-<!-- </desc> -->
-<!-- </func> -->
+ <func>
+ <name> pkix_decode_cert(Cert, otp|plain) -> #'Certificate'{} | #'OTPCertificate'{}</name>
+ <fsummary> Decodes an asn1 der encoded pkix x509 certificate.</fsummary>
+ <type>
+ <v>Cert = der_encoded()</v>
+ </type>
+ <desc>
+ <p>Decodes an asn1 der encoded pkix certificate. The otp option
+ will use the customized asn1 specification OTP-PKIX.asn1 for
+ decoding and also recursively decode most of the standard
+ parts.</p>
+ </desc>
+ </func>
-<!-- <func> -->
-<!-- <name>pkix_path_validation(TrustedCert, CertChain, Options) -> {ok, Result} | {error, Reason}</name> -->
-
-<!-- <fsummary>Performs a basic path validation according to RFC 3280</fsummary> -->
-<!-- <type> -->
-<!-- <v>TrustedCert = asn1_der_encoded()</v> -->
-<!-- <v>CertChain = [asn1_der_encoded()]</v> -->
-<!-- <v>Options = [{Option, Value}]</v> -->
-<!-- <v>Result = {{algorithm(), public_key(), -->
-<!-- public_key_params()}, policy_tree()}</v> -->
-<!-- </type> -->
+ <func>
+ <name>pkix_encode(Asn1Type, Entity, otp | plain) -> der_encoded()</name>
+ <fsummary>Der encodes a pkix x509 certificate or part of such a
+ certificate.</fsummary>
+ <type>
+ <v>Asn1Type = atom()</v>
+ <d>The asn1 type can be 'Certificate', 'OTPCertificate' or a subtype of either .</d>
+ </type>
+ <desc>
+ <p>Der encodes a pkix x509 certificate or part of such a
+ certificate. This function must be used for encoding certificates or parts of certificates
+ that are decoded/created on the otp format, whereas for the plain format this
+ function will directly call der_encode/2. </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>pkix_is_issuer(Cert, IssuerCert) -> boolean()</name>
+ <fsummary> Checks if <c>IssuerCert</c> issued <c>Cert</c> </fsummary>
+ <type>
+ <v>Cert = der_encode() | #'OTPCertificate'{}</v>
+ <v>IssuerCert = der_encode() | #'OTPCertificate'{}</v>
+ </type>
+ <desc>
+ <p> Checks if <c>IssuerCert</c> issued <c>Cert</c> </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>pkix_is_fixed_dh_cert(Cert) -> boolean()</name>
+ <fsummary> Checks if a Certificate is a fixed Diffie-Hellman Cert.</fsummary>
+ <type>
+ <v>Cert = der_encode() | #'OTPCertificate'{}</v>
+ </type>
+ <desc>
+ <p> Checks if a Certificate is a fixed Diffie-Hellman Cert.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>pkix_is_self_signed(Cert) -> boolean()</name>
+ <fsummary> Checks if a Certificate is self signed.</fsummary>
+ <type>
+ <v>Cert = der_encode() | #'OTPCertificate'{}</v>
+ </type>
+ <desc>
+ <p> Checks if a Certificate is self signed.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>pkix_issuer_id(Cert, IssuedBy) -> {ok, IssuerID} | {error, Reason}</name>
+ <fsummary> Returns the issuer id.</fsummary>
+ <type>
+ <v>Cert = der_encode() | #'OTPCertificate'{}</v>
+ <v>IssuedBy = self | other</v>
+ <v>IssuerID = {integer(), {rdnSequence, [#'AttributeTypeAndValue'{}]}}</v>
+ <d>The issuer id consists of the serial number and the issuers name.</d>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p> Returns the issuer id.</p>
+ </desc>
+ </func>
-<!-- <desc> -->
-<!-- <p>Available options are: </p> -->
-<!-- <taglist> -->
-<!-- <tag>{validate_extension_fun, fun()}</tag> -->
-<!-- <item> A fun behaving according to the following outline: -->
-<!-- <code> -->
-<!-- [...] -->
-<!-- ValidateExtensionFun = fun(Extensions, UserState) -> -->
-<!-- validate_extensions(Extensions, UserState, []) -->
-<!-- end, -->
-<!-- [...] -->
+ <func>
+ <name>pkix_normalize_name(Issuer) -> Normalized</name>
+ <fsummary>Normalizes a issuer name so that it can be easily
+ compared to another issuer name. </fsummary>
+ <type>
+ <v>Issuer = {rdnSequence,[#'AttributeTypeAndValue'{}]}</v>
+ <v>Normalized = {rdnSequence, [#'AttributeTypeAndValue'{}]}</v>
+ </type>
+ <desc>
+ <p>Normalizes a issuer name so that it can be easily
+ compared to another issuer name.</p>
+ </desc>
+ </func>
+
+ <!-- <func> -->
+ <!-- <name>pkix_path_validation()</name> -->
+ <!-- <fsummary> Performs a basic path validation according to RFC 5280.</fsummary> -->
+ <!-- <type> -->
+ <!-- <v></v> -->
+ <!-- </type> -->
+ <!-- <desc> -->
+ <!-- <p> Performs a basic path validation according to RFC 5280.</p> -->
+ <!-- </desc> -->
+ <!-- </func> -->
-<!-- validate_extensions([], UserState, UnknowExtension) -> -->
-<!-- {UserState, UnknowExtension}; -->
-<!-- validate_extensions([#'Extension'{} = Ext | Rest], UserState, UnknowExtension) -> -->
-<!-- case valid_extension(Ext) of -->
-<!-- {true, NewUserState} -> -->
-<!-- validate_extensions(Rest, NewUserState, UnknowExtension); -->
-<!-- unknown -> -->
-<!-- validate_extensions(Rest, UserState, [Ext | UnknowExtension]); -->
-<!-- {false, Reason} -> -->
-<!-- throw(bad_cert, Reason) -->
-<!-- end. -->
-<!-- </code> -->
-
-<!-- </item> -->
-
-<!-- <tag>{policy_set, [oid()]}</tag> -->
-<!-- <item>A set of certificate policy -->
-<!-- identifiers naming the policies that are acceptable to the -->
-<!-- certificate user. If the user is not concerned about -->
-<!-- certificate policy there is no need -->
-<!-- to set this option. Defaults to the -->
-<!-- special value [?anyPolicy]. -->
-<!-- </item> -->
-
-<!-- <tag>{policy_mapping, boolean()}</tag> -->
-<!-- <item>Indicates if policy -->
-<!-- mapping, initially, is allowed in the certification path. -->
-<!-- Defaults to false. -->
-<!-- </item> -->
-
-<!-- <tag> {explicit_policy, boolean()}</tag> -->
-<!-- <item>Indicates if the path, initially, must be -->
-<!-- valid for at least one of the certificate policies in the user -->
-<!-- specified policy set. -->
-<!-- Defaults to false. -->
-<!-- </item> -->
+
+ <func>
+ <name>pkix_sign(#'OTPTBSCertificate'{}, Key) -> der_encode()</name>
+ <fsummary>Signs certificate.</fsummary>
+ <type>
+ <v>Key = rsa_public_key() | dsa_public_key()</v>
+ </type>
+ <desc>
+ <p>Signs a 'OTPTBSCertificate'. Returns the corresponding
+ der encoded certificate.</p>
+ </desc>
+ </func>
-<!-- <tag>{inhibit_any_policy, boolean()}</tag> -->
-<!-- <item>Indicates whether the anyPolicy OID, initially, should -->
-<!-- be processed if it is included in a certificate. -->
-<!-- Defaults to false. -->
-<!-- </item> -->
-
-<!-- </taglist> -->
-
-<!-- <p>Performs a basic path validation according to RFC 3280, -->
-<!-- e.i. signature validation, time validation, issuer validation, -->
-<!-- alternative subject name validation, CRL validation, policy -->
-<!-- validation and checks that no unknown extensions -->
-<!-- are marked as critical. The option <c>validate_extension_fun</c> -->
-<!-- may be used to validate application specific extensions. If -->
-<!-- a validation criteria is found to be invalid the validation process -->
-<!-- will immediately be stopped and this functions will return -->
-<!-- {error, Reason}. -->
-<!-- </p> -->
-<!-- </desc> -->
-<!-- </func> -->
+ <func>
+ <name>pkix_verify(Cert, Key) -> boolean()</name>
+ <fsummary> Verify pkix x.509 certificate signature.</fsummary>
+ <type>
+ <v>Cert = der_encode()</v>
+ <v>Key = rsa_public_key() | dsa_public_key()</v>
+ </type>
+ <desc>
+ <p> Verify pkix x.509 certificate signature.</p>
+ </desc>
+ </func>
-<!-- <func> -->
-<!-- <name>sign(DigestOrTBSCert, Key) -> </name> -->
-<!-- <name>sign(DigestOrTBSCert, Key, KeyParams) -> {ok, SignatureOrDerCert} | {error, Reason}</name> -->
-<!-- <fsummary>Signs Digest/Certificate using Key.</fsummary> -->
-<!-- <type> -->
-<!-- <v>DigestOrTBSCert = binary() | x509_tbs_certificate()</v> -->
-<!-- <v>Key = private_key()</v> -->
-<!-- <v>SignatureORDerCert = binary() | der_bin() </v> -->
-<!-- <v>Reason = term() </v> -->
-<!-- </type> -->
-<!-- <desc> -->
-<!-- <p> Signs Digest/Certificate using Key, in the later -->
-<!-- case a der encoded x509_certificate() will be returned. </p> -->
-<!-- </desc> -->
-<!-- </func> -->
+ <func>
+ <name>sign(Msg, DigestType, Key) -> binary()</name>
+ <fsummary> Create digital signature.</fsummary>
+ <type>
+ <v>Msg = binary()</v>
+ <d>The msg is either the binary "plain text" data to be
+ signed or in the case that digest type is <c>none</c>
+ it is the hashed value of "plain text" i.e. the digest.</d>
+ <v>DigestType = rsa_digest_type() | dsa_digest_type()</v>
+ <v>Key = rsa_public_key() | dsa_public_key()</v>
+ </type>
+ <desc>
+ <p> Creates a digital signature.</p>
+ </desc>
+ </func>
-<!-- <func> -->
-<!-- <name>verify_signature(Digest, Signature, Key) -> </name> -->
-<!-- <name>verify_signature(DerCert, Key, KeyParams) -> </name> -->
-<!-- <name>verify_signature(Digest, Signature, Key, Params) -> Verified </name> -->
-<!-- <fsummary> Verifies the signature. </fsummary> -->
-<!-- <type> -->
-<!-- <v>Digest = binary() </v> -->
-<!-- <v>DerCert = der_bin() </v> -->
-<!-- <v>Signature = binary() </v> -->
-<!-- <v>Key = public_key() </v> -->
-<!-- <v>Params = key_params()</v> -->
-<!-- <v>Verified = boolean()</v> -->
-<!-- </type> -->
-<!-- <desc> -->
-<!-- <p> Verifies the signature Signature. If the key is an rsa-key no -->
-<!-- paramters are neeed.</p> -->
-<!-- </desc> -->
-<!-- </func> -->
+ <func>
+ <name>verify(Msg, DigestType, Signature, Key) -> boolean()</name>
+ <fsummary>Verifies a digital signature.</fsummary>
+ <type>
+ <v>Msg = binary()</v>
+ <d>The msg is either the binary "plain text" data
+ or in the case that digest type is <c>none</c>
+ it is the hashed value of "plain text" i.e. the digest.</d>
+ <v>DigestType = rsa_digest_type() | dsa_digest_type()</v>
+ <v>Signature = binary()</v>
+ <v>Key = rsa_public_key() | dsa_public_key()</v>
+ </type>
+ <desc>
+ <p>Verifies a digital signature</p>
+ </desc>
+ </func>
+
</funcs>
</erlref>
diff --git a/lib/public_key/include/public_key.hrl b/lib/public_key/include/public_key.hrl
index fbce10f0eb..4950597fb5 100644
--- a/lib/public_key/include/public_key.hrl
+++ b/lib/public_key/include/public_key.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -28,6 +28,17 @@
algorithm,
parameters = asn1_NOVALUE}).
+-define(DEFAULT_VERIFYFUN,
+ {fun(_,{bad_cert, _} = Reason, _) ->
+ {fail, Reason};
+ (_,{extension, _}, UserState) ->
+ {unknown, UserState};
+ (_, valid, UserState) ->
+ {valid, UserState};
+ (_, valid_peer, UserState) ->
+ {valid, UserState}
+ end, []}).
+
-record(path_validation_state, {
valid_policy_tree,
explicit_policy,
@@ -42,7 +53,7 @@
working_public_key_parameters,
working_issuer_name,
max_path_length,
- acc_errors, %% If verify_none option is set
+ verify_fun,
user_state
}).
@@ -59,4 +70,13 @@
interim_reasons_mask
}).
+
+-type der_encoded() :: binary().
+-type decrypt_der() :: binary().
+-type pki_asn1_type() :: 'Certificate' | 'RSAPrivateKey'
+ | 'DSAPrivateKey' | 'DHParameter'.
+-type pem_entry() :: {pki_asn1_type(), der_encoded() | decrypt_der(),
+ not_encrypted | {Cipher :: string(), Salt :: binary()}}.
+-type asn1_type() :: atom(). %% see "OTP-PUB-KEY.hrl
+
-endif. % -ifdef(public_key).
diff --git a/lib/public_key/src/Makefile b/lib/public_key/src/Makefile
index c30399f33a..51f405361b 100644
--- a/lib/public_key/src/Makefile
+++ b/lib/public_key/src/Makefile
@@ -42,8 +42,7 @@ MODULES = \
public_key \
pubkey_pem \
pubkey_cert \
- pubkey_cert_records \
- pubkey_crypto
+ pubkey_cert_records
HRL_FILES = $(INCLUDE)/public_key.hrl
diff --git a/lib/public_key/src/pubkey_cert.erl b/lib/public_key/src/pubkey_cert.erl
index 0651dcec29..c8953c6818 100644
--- a/lib/public_key/src/pubkey_cert.erl
+++ b/lib/public_key/src/pubkey_cert.erl
@@ -23,14 +23,13 @@
-include("public_key.hrl").
--export([verify_signature/3,
- init_validation_state/3, prepare_for_next_cert/2,
+-export([init_validation_state/3, prepare_for_next_cert/2,
validate_time/3, validate_signature/6,
validate_issuer/4, validate_names/6,
validate_revoked_status/3, validate_extensions/4,
- validate_unknown_extensions/3,
normalize_general_name/1, digest_type/1, is_self_signed/1,
- is_issuer/2, issuer_id/2, is_fixed_dh_cert/1]).
+ is_issuer/2, issuer_id/2, is_fixed_dh_cert/1,
+ verify_data/1, verify_fun/4]).
-define(NULL, 0).
@@ -38,10 +37,22 @@
%% Internal application API
%%====================================================================
-verify_signature(DerCert, Key, KeyParams) ->
- {ok, OtpCert} = pubkey_cert_records:decode_cert(DerCert, otp),
- verify_signature(OtpCert, DerCert, Key, KeyParams).
+%%--------------------------------------------------------------------
+-spec verify_data(der_encoded()) -> {md5 | sha, binary(), binary()}.
+%%
+%% Description: Extracts data from DerCert needed to call public_key:verify/4.
+%%--------------------------------------------------------------------
+verify_data(DerCert) ->
+ {ok, OtpCert} = pubkey_cert_records:decode_cert(DerCert),
+ extract_verify_data(OtpCert, DerCert).
+%%--------------------------------------------------------------------
+-spec init_validation_state(#'OTPCertificate'{}, integer(), list()) ->
+ #path_validation_state{}.
+%%
+%% Description: Creates inital version of path_validation_state for
+%% basic path validation of x509 certificates.
+%%--------------------------------------------------------------------
init_validation_state(#'OTPCertificate'{} = OtpCert, DefaultPathLen,
Options) ->
PolicyTree = #policy_tree_node{valid_policy = ?anyPolicy,
@@ -56,16 +67,23 @@ init_validation_state(#'OTPCertificate'{} = OtpCert, DefaultPathLen,
Options, false)),
PolicyMapping = policy_indicator(MaxLen,
proplists:get_value(policy_mapping, Options, false)),
- AccErrors = proplists:get_value(acc_errors, Options, []),
- State = #path_validation_state{max_path_length = MaxLen,
- valid_policy_tree = PolicyTree,
- explicit_policy = ExplicitPolicy,
- inhibit_any_policy = InhibitAnyPolicy,
- policy_mapping = PolicyMapping,
- acc_errors = AccErrors,
+ {VerifyFun, UserState} = proplists:get_value(verify_fun, Options, ?DEFAULT_VERIFYFUN),
+ State = #path_validation_state{max_path_length = MaxLen,
+ valid_policy_tree = PolicyTree,
+ explicit_policy = ExplicitPolicy,
+ inhibit_any_policy = InhibitAnyPolicy,
+ policy_mapping = PolicyMapping,
+ verify_fun = VerifyFun,
+ user_state = UserState,
cert_num = 0},
prepare_for_next_cert(OtpCert, State).
+%%--------------------------------------------------------------------
+-spec prepare_for_next_cert(#'OTPCertificate'{}, #path_validation_state{}) ->
+ #path_validation_state{}.
+%%
+%% Description: Update path_validation_state for next iteration.
+%%--------------------------------------------------------------------
prepare_for_next_cert(OtpCert, ValidationState = #path_validation_state{
working_public_key_algorithm = PrevAlgo,
working_public_key_parameters =
@@ -92,8 +110,14 @@ prepare_for_next_cert(OtpCert, ValidationState = #path_validation_state{
working_issuer_name = Issuer,
cert_num = ValidationState#path_validation_state.cert_num + 1
}.
-
-validate_time(OtpCert, AccErr, Verify) ->
+
+ %%--------------------------------------------------------------------
+-spec validate_time(#'OTPCertificate'{}, term(), fun()) -> term().
+%%
+%% Description: Check that the certificate validity period includes the
+%% current time.
+%%--------------------------------------------------------------------
+validate_time(OtpCert, UserState, VerifyFun) ->
TBSCert = OtpCert#'OTPCertificate'.tbsCertificate,
{'Validity', NotBeforeStr, NotAfterStr}
= TBSCert#'OTPTBSCertificate'.validity,
@@ -103,34 +127,52 @@ validate_time(OtpCert, AccErr, Verify) ->
case ((NotBefore =< Now) and (Now =< NotAfter)) of
true ->
- AccErr;
+ UserState;
false ->
- not_valid({bad_cert, cert_expired}, Verify, AccErr)
+ verify_fun(OtpCert, {bad_cert, cert_expired}, UserState, VerifyFun)
end.
-
-validate_issuer(OtpCert, Issuer, AccErr, Verify) ->
+%%--------------------------------------------------------------------
+-spec validate_issuer(#'OTPCertificate'{}, term(), term(), fun()) -> term().
+%%
+%% Description: Check that the certificate issuer name is the working_issuer_name
+%% in path_validation_state.
+%%--------------------------------------------------------------------
+validate_issuer(OtpCert, Issuer, UserState, VerifyFun) ->
TBSCert = OtpCert#'OTPCertificate'.tbsCertificate,
case is_issuer(Issuer, TBSCert#'OTPTBSCertificate'.issuer) of
true ->
- AccErr;
+ UserState;
_ ->
- not_valid({bad_cert, invalid_issuer}, Verify, AccErr)
+ verify_fun(OtpCert, {bad_cert, invalid_issuer}, UserState, VerifyFun)
end.
-
+%%--------------------------------------------------------------------
+-spec validate_signature(#'OTPCertificate'{}, der_encoded(),
+ term(),term(), term(), fun()) -> term().
+
+%%
+%% Description: Check that the signature on the certificate can be verified using
+%% working_public_key_algorithm, the working_public_key, and
+%% the working_public_key_parameters in path_validation_state.
+%%--------------------------------------------------------------------
validate_signature(OtpCert, DerCert, Key, KeyParams,
- AccErr, Verify) ->
+ UserState, VerifyFun) ->
case verify_signature(OtpCert, DerCert, Key, KeyParams) of
true ->
- AccErr;
+ UserState;
false ->
- not_valid({bad_cert, invalid_signature}, Verify, AccErr)
+ verify_fun(OtpCert, {bad_cert, invalid_signature}, UserState, VerifyFun)
end.
-
-validate_names(OtpCert, Permit, Exclude, Last, AccErr, Verify) ->
+%%--------------------------------------------------------------------
+-spec validate_names(#'OTPCertificate'{}, list(), list(),
+ term(), term(), fun())-> term().
+%%
+%% Description: Validate Subject Alternative Name.
+%%--------------------------------------------------------------------
+validate_names(OtpCert, Permit, Exclude, Last, UserState, VerifyFun) ->
case is_self_signed(OtpCert) andalso (not Last) of
true ->
- AccErr;
+ UserState;
false ->
TBSCert = OtpCert#'OTPCertificate'.tbsCertificate,
Subject = TBSCert#'OTPTBSCertificate'.subject,
@@ -143,8 +185,10 @@ validate_names(OtpCert, Permit, Exclude, Last, AccErr, Verify) ->
Name = [{directoryName, Subject}|EmailAddress],
AltNames = case AltSubject of
- undefined -> [];
- _ -> AltSubject#'Extension'.extnValue
+ undefined ->
+ [];
+ _ ->
+ AltSubject#'Extension'.extnValue
end,
case (is_permitted(Name, Permit) andalso
@@ -152,65 +196,74 @@ validate_names(OtpCert, Permit, Exclude, Last, AccErr, Verify) ->
(not is_excluded(Name, Exclude)) andalso
(not is_excluded(AltNames, Exclude))) of
true ->
- AccErr;
+ UserState;
false ->
- not_valid({bad_cert, name_not_permitted},
- Verify, AccErr)
+ verify_fun(OtpCert, {bad_cert, name_not_permitted},
+ UserState, VerifyFun)
end
end.
-
-%% See rfc3280 4.1.2.6 Subject: regarding emails.
-extract_email({rdnSequence, List}) ->
- extract_email2(List).
-extract_email2([[#'AttributeTypeAndValue'{type=?'id-emailAddress',
- value=Mail}]|_]) ->
- [{rfc822Name, Mail}];
-extract_email2([_|Rest]) ->
- extract_email2(Rest);
-extract_email2([]) -> [].
-
-validate_revoked_status(_OtpCert, _Verify, AccErr) ->
- %% true |
+%%--------------------------------------------------------------------
+-spec validate_revoked_status(#'OTPCertificate'{}, term(), fun()) ->
+ term().
+%%
+%% Description: Check if certificate has been revoked.
+%%--------------------------------------------------------------------
+validate_revoked_status(_OtpCert, UserState, _VerifyFun) ->
+ %% TODO: Implement or leave for application?!
+ %% valid |
%% throw({bad_cert, cert_revoked})
- AccErr.
-
-validate_extensions(OtpCert, ValidationState, Verify, AccErr) ->
+ UserState.
+%%--------------------------------------------------------------------
+-spec validate_extensions(#'OTPCertificate'{}, #path_validation_state{},
+ term(), fun())->
+ {#path_validation_state{}, UserState :: term()}.
+%%
+%% Description: Check extensions included in basic path validation.
+%%--------------------------------------------------------------------
+validate_extensions(OtpCert, ValidationState, UserState, VerifyFun) ->
TBSCert = OtpCert#'OTPCertificate'.tbsCertificate,
- Extensions = TBSCert#'OTPTBSCertificate'.extensions,
- validate_extensions(Extensions, ValidationState, no_basic_constraint,
- is_self_signed(OtpCert), [], Verify, AccErr).
-
-validate_unknown_extensions([], AccErr, _Verify) ->
- AccErr;
-validate_unknown_extensions([#'Extension'{critical = true} | _],
- AccErr, Verify) ->
- not_valid({bad_cert, unknown_critical_extension}, Verify, AccErr);
-validate_unknown_extensions([#'Extension'{critical = false} | Rest],
- AccErr, Verify) ->
- validate_unknown_extensions(Rest, AccErr, Verify).
-
+ case TBSCert#'OTPTBSCertificate'.version of
+ N when N >= 3 ->
+ Extensions = TBSCert#'OTPTBSCertificate'.extensions,
+ validate_extensions(OtpCert, Extensions,
+ ValidationState, no_basic_constraint,
+ is_self_signed(OtpCert), UserState, VerifyFun);
+ _ -> %% Extensions not present in versions 1 & 2
+ {ValidationState, UserState}
+ end.
+%%--------------------------------------------------------------------
+-spec normalize_general_name({rdnSequence, term()}) -> {rdnSequence, term()}.
+%%
+%% Description: Normalizes a general name so that it can be easily
+%% compared to another genral name.
+%%--------------------------------------------------------------------
normalize_general_name({rdnSequence, Issuer}) ->
- NormIssuer = normalize_general_name(Issuer),
- {rdnSequence, NormIssuer};
-
-normalize_general_name(Issuer) ->
- Normalize = fun([{Description, Type, {printableString, Value}}]) ->
- NewValue = string:to_lower(strip_spaces(Value)),
- [{Description, Type, {printableString, NewValue}}];
- (Atter) ->
- Atter
- end,
- lists:sort(lists:map(Normalize, Issuer)).
+ NormIssuer = do_normalize_general_name(Issuer),
+ {rdnSequence, NormIssuer}.
+%%--------------------------------------------------------------------
+-spec is_self_signed(#'OTPCertificate'{}) -> boolean().
+%%
+%% Description: Checks if the certificate is self signed.
+%%--------------------------------------------------------------------
is_self_signed(#'OTPCertificate'{tbsCertificate=
#'OTPTBSCertificate'{issuer = Issuer,
subject = Subject}}) ->
is_issuer(Issuer, Subject).
-
+%%--------------------------------------------------------------------
+-spec is_issuer({rdnSequence, term()}, {rdnSequence, term()}) -> boolean().
+%%
+%% Description: Checks if <Issuer> issued <Candidate>.
+%%--------------------------------------------------------------------
is_issuer({rdnSequence, Issuer}, {rdnSequence, Candidate}) ->
is_dir_name(Issuer, Candidate, true).
-
+%%--------------------------------------------------------------------
+-spec issuer_id(#'OTPCertificate'{}, self | other) ->
+ {ok, {integer(), term()}} | {error, issuer_not_found}.
+%%
+%% Description: Extracts the issuer id from a certificate if possible.
+%%--------------------------------------------------------------------
issuer_id(Otpcert, other) ->
TBSCert = Otpcert#'OTPCertificate'.tbsCertificate,
Extensions = extensions_list(TBSCert#'OTPTBSCertificate'.extensions),
@@ -227,7 +280,12 @@ issuer_id(Otpcert, self) ->
SerialNr = TBSCert#'OTPTBSCertificate'.serialNumber,
{ok, {SerialNr, normalize_general_name(Issuer)}}.
-
+%%--------------------------------------------------------------------
+-spec is_fixed_dh_cert(#'OTPCertificate'{}) -> boolean().
+%%
+%% Description: Checks if the certificate can be be used
+%% for DH key agreement.
+%%--------------------------------------------------------------------
is_fixed_dh_cert(#'OTPCertificate'{tbsCertificate =
#'OTPTBSCertificate'{subjectPublicKeyInfo =
SubjectPublicKeyInfo,
@@ -235,31 +293,79 @@ is_fixed_dh_cert(#'OTPCertificate'{tbsCertificate =
Extensions}}) ->
is_fixed_dh_cert(SubjectPublicKeyInfo, extensions_list(Extensions)).
+
+%%--------------------------------------------------------------------
+-spec verify_fun(#'OTPCertificate'{}, {bad_cert, atom()} | {extension, #'Extension'{}}|
+ valid | valid_peer, term(), fun()) -> term().
+%%
+%% Description: Gives the user application the opportunity handle path
+%% validation errors and unknown extensions and optional do other
+%% things with a validated certificate.
+%% --------------------------------------------------------------------
+verify_fun(Otpcert, Result, UserState0, VerifyFun) ->
+ case VerifyFun(Otpcert, Result, UserState0) of
+ {valid,UserState} ->
+ UserState;
+ {fail, Reason} ->
+ case Result of
+ {bad_cert, _} ->
+ throw(Result);
+ _ ->
+ throw({bad_cert, Reason})
+ end;
+ {unknown, UserState} ->
+ case Result of
+ {extension, #'Extension'{critical = true}} ->
+ throw({bad_cert, unknown_critical_extension});
+ _ ->
+ UserState
+ end
+ end.
+
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
+do_normalize_general_name(Issuer) ->
+ Normalize = fun([{Description, Type, {printableString, Value}}]) ->
+ NewValue = string:to_lower(strip_spaces(Value)),
+ [{Description, Type, {printableString, NewValue}}];
+ (Atter) ->
+ Atter
+ end,
+ lists:sort(lists:map(Normalize, Issuer)).
+
+%% See rfc3280 4.1.2.6 Subject: regarding emails.
+extract_email({rdnSequence, List}) ->
+ extract_email2(List).
+extract_email2([[#'AttributeTypeAndValue'{type=?'id-emailAddress',
+ value=Mail}]|_]) ->
+ [{rfc822Name, Mail}];
+extract_email2([_|Rest]) ->
+ extract_email2(Rest);
+extract_email2([]) -> [].
extensions_list(asn1_NOVALUE) ->
[];
extensions_list(Extensions) ->
Extensions.
-not_valid(Error, true, _) ->
- throw(Error);
-not_valid(Error, false, AccErrors) ->
- [Error | AccErrors].
-verify_signature(OtpCert, DerCert, Key, KeyParams) ->
- %% Signature is an ASN1 compact bit string
+extract_verify_data(OtpCert, DerCert) ->
{0, Signature} = OtpCert#'OTPCertificate'.signature,
SigAlgRec = OtpCert#'OTPCertificate'.signatureAlgorithm,
SigAlg = SigAlgRec#'SignatureAlgorithm'.algorithm,
- EncTBSCert = encoded_tbs_cert(DerCert),
- verify(SigAlg, EncTBSCert, Signature, Key, KeyParams).
+ PlainText = encoded_tbs_cert(DerCert),
+ DigestType = digest_type(SigAlg),
+ {DigestType, PlainText, Signature}.
-verify(Alg, PlainText, Signature, Key, KeyParams) ->
- public_key:verify_signature(PlainText, digest_type(Alg),
- Signature, Key, KeyParams).
+verify_signature(OtpCert, DerCert, Key, KeyParams) ->
+ {DigestType, PlainText, Signature} = extract_verify_data(OtpCert, DerCert),
+ case Key of
+ #'RSAPublicKey'{} ->
+ public_key:verify(PlainText, DigestType, Signature, Key);
+ _ ->
+ public_key:verify(PlainText, DigestType, Signature, {Key, KeyParams})
+ end.
encoded_tbs_cert(Cert) ->
{ok, PKIXCert} =
@@ -288,10 +394,12 @@ public_key_info(PublicKeyInfo,
NewPublicKeyParams =
case PublicKeyParams of
- 'NULL' when WorkingAlgorithm == Algorithm ->
+ {null, 'NULL'} when WorkingAlgorithm == Algorithm ->
WorkingParams;
- _ ->
- PublicKeyParams
+ {params, Params} ->
+ Params;
+ Params ->
+ Params
end,
{Algorithm, PublicKey, NewPublicKeyParams}.
@@ -369,210 +477,179 @@ select_extension(Id, [_ | Extensions]) ->
select_extension(Id, Extensions).
%% No extensions present
-validate_extensions(asn1_NOVALUE, ValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify, AccErr) ->
- validate_extensions([], ValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify, AccErr);
-
-validate_extensions([], ValidationState, basic_constraint, _SelfSigned,
- UnknownExtensions, _Verify, AccErr) ->
- {ValidationState, UnknownExtensions, AccErr};
-validate_extensions([], ValidationState =
- #path_validation_state{max_path_length = Len,
- last_cert = Last},
- no_basic_constraint, SelfSigned, UnknownExtensions,
- Verify, AccErr0) ->
+validate_extensions(OtpCert, asn1_NOVALUE, ValidationState, ExistBasicCon,
+ SelfSigned, UserState, VerifyFun) ->
+ validate_extensions(OtpCert, [], ValidationState, ExistBasicCon,
+ SelfSigned, UserState, VerifyFun);
+
+validate_extensions(_,[], ValidationState, basic_constraint, _SelfSigned,
+ UserState, _) ->
+ {ValidationState, UserState};
+validate_extensions(OtpCert, [], ValidationState =
+ #path_validation_state{max_path_length = Len,
+ last_cert = Last},
+ no_basic_constraint, SelfSigned, UserState0, VerifyFun) ->
case Last of
true when SelfSigned ->
- {ValidationState, UnknownExtensions, AccErr0};
+ {ValidationState, UserState0};
true ->
{ValidationState#path_validation_state{max_path_length = Len - 1},
- UnknownExtensions, AccErr0};
+ UserState0};
%% basic_constraint must appear in certs used for digital sign
%% see 4.2.1.10 in rfc 3280
false ->
- AccErr = not_valid({bad_cert, missing_basic_constraint},
- Verify, AccErr0),
+ UserState = verify_fun(OtpCert, {bad_cert, missing_basic_constraint},
+ UserState0, VerifyFun),
case SelfSigned of
true ->
- {ValidationState, UnknownExtensions, AccErr};
+ {ValidationState, UserState};
false ->
{ValidationState#path_validation_state{max_path_length =
- Len - 1},
- UnknownExtensions, AccErr}
+ Len - 1},
+ UserState}
end
end;
-validate_extensions([#'Extension'{extnID = ?'id-ce-basicConstraints',
+validate_extensions(OtpCert,
+ [#'Extension'{extnID = ?'id-ce-basicConstraints',
extnValue =
- #'BasicConstraints'{cA = true,
- pathLenConstraint = N}} |
+ #'BasicConstraints'{cA = true,
+ pathLenConstraint = N}} |
Rest],
- ValidationState =
- #path_validation_state{max_path_length = Len}, _,
- SelfSigned, UnknownExtensions, Verify, AccErr) ->
- Length = if SelfSigned -> min(N, Len);
- true -> min(N, Len-1)
+ ValidationState =
+ #path_validation_state{max_path_length = Len}, _,
+ SelfSigned, UserState, VerifyFun) ->
+ Length = if SelfSigned -> erlang:min(N, Len);
+ true -> erlang:min(N, Len-1)
end,
- validate_extensions(Rest,
+ validate_extensions(OtpCert, Rest,
ValidationState#path_validation_state{max_path_length =
- Length},
- basic_constraint, SelfSigned, UnknownExtensions,
- Verify, AccErr);
+ Length},
+ basic_constraint, SelfSigned,
+ UserState, VerifyFun);
%% The pathLenConstraint field is meaningful only if cA is set to
%% TRUE.
-validate_extensions([#'Extension'{extnID = ?'id-ce-basicConstraints',
- extnValue =
- #'BasicConstraints'{cA = false}} |
- Rest], ValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify, AccErr) ->
- validate_extensions(Rest, ValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify, AccErr);
-
-%%
-validate_extensions([#'Extension'{extnID = ?'id-ce-keyUsage',
- extnValue = KeyUse
- } | Rest],
- #path_validation_state{last_cert=Last} = ValidationState,
- ExistBasicCon, SelfSigned, UnknownExtensions,
- Verify, AccErr0) ->
+validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-basicConstraints',
+ extnValue =
+ #'BasicConstraints'{cA = false}} |
+ Rest], ValidationState, ExistBasicCon,
+ SelfSigned, UserState, VerifyFun) ->
+ validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon,
+ SelfSigned, UserState, VerifyFun);
+
+validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-keyUsage',
+ extnValue = KeyUse
+ } | Rest],
+ #path_validation_state{last_cert=Last} = ValidationState,
+ ExistBasicCon, SelfSigned,
+ UserState0, VerifyFun) ->
case Last orelse is_valid_key_usage(KeyUse, keyCertSign) of
true ->
- validate_extensions(Rest, ValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify,
- AccErr0);
+ validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon,
+ SelfSigned, UserState0, VerifyFun);
false ->
- AccErr = not_valid({bad_cert, invalid_key_usage}, Verify, AccErr0),
- validate_extensions(Rest, ValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify,
- AccErr)
+ UserState = verify_fun(OtpCert, {bad_cert, invalid_key_usage},
+ UserState0, VerifyFun),
+ validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon,
+ SelfSigned, UserState, VerifyFun)
end;
-validate_extensions([#'Extension'{extnID = ?'id-ce-subjectAltName',
- extnValue = Names} | Rest],
- ValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify, AccErr0) ->
+validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-subjectAltName',
+ extnValue = Names,
+ critical = true} = Ext | Rest],
+ ValidationState, ExistBasicCon,
+ SelfSigned, UserState0, VerifyFun) ->
case validate_subject_alt_names(Names) of
- true when Names =/= [] ->
- validate_extensions(Rest, ValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify,
- AccErr0);
- _ ->
- AccErr =
- not_valid({bad_cert, invalid_subject_altname},
- Verify, AccErr0),
- validate_extensions(Rest, ValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify,
- AccErr)
+ true ->
+ validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon,
+ SelfSigned, UserState0, VerifyFun);
+ false ->
+ UserState = verify_fun(OtpCert, {extension, Ext},
+ UserState0, VerifyFun),
+ validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon,
+ SelfSigned, UserState, VerifyFun)
end;
-%% This extension SHOULD NOT be marked critical. Its value
-%% does not have to be further validated at this point.
-validate_extensions([#'Extension'{extnID = ?'id-ce-issuerAltName',
- extnValue = _} | Rest],
- ValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify, AccErr) ->
- validate_extensions(Rest, ValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify, AccErr);
-
-%% This extension MUST NOT be marked critical.Its value
-%% does not have to be further validated at this point.
-validate_extensions([#'Extension'{extnID = Id,
- extnValue = _,
- critical = false} | Rest],
- ValidationState,
- ExistBasicCon, SelfSigned, UnknownExtensions,
- Verify, AccErr)
- when Id == ?'id-ce-subjectKeyIdentifier';
- Id == ?'id-ce-authorityKeyIdentifier'->
- validate_extensions(Rest, ValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify, AccErr);
-
-validate_extensions([#'Extension'{extnID = ?'id-ce-nameConstraints',
+validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-nameConstraints',
extnValue = NameConst} | Rest],
ValidationState,
- ExistBasicCon, SelfSigned, UnknownExtensions,
- Verify, AccErr) ->
+ ExistBasicCon, SelfSigned, UserState, VerifyFun) ->
Permitted = NameConst#'NameConstraints'.permittedSubtrees,
Excluded = NameConst#'NameConstraints'.excludedSubtrees,
NewValidationState = add_name_constraints(Permitted, Excluded,
ValidationState),
- validate_extensions(Rest, NewValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify, AccErr);
-
+ validate_extensions(OtpCert, Rest, NewValidationState, ExistBasicCon,
+ SelfSigned, UserState, VerifyFun);
-validate_extensions([#'Extension'{extnID = ?'id-ce-certificatePolicies',
- critical = true} | Rest], ValidationState,
- ExistBasicCon, SelfSigned,
- UnknownExtensions, Verify, AccErr0) ->
+validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-certificatePolicies',
+ critical = true} = Ext| Rest], ValidationState,
+ ExistBasicCon, SelfSigned, UserState0, VerifyFun) ->
%% TODO: Remove this clause when policy handling is
%% fully implemented
- AccErr =
- not_valid({bad_cert, unknown_critical_extension}, Verify, AccErr0),
- validate_extensions(Rest, ValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify, AccErr);
-
-validate_extensions([#'Extension'{extnID = ?'id-ce-certificatePolicies',
- extnValue = #'PolicyInformation'{
- policyIdentifier = Id,
- policyQualifiers = Qualifier}}
- | Rest], #path_validation_state{valid_policy_tree = Tree}
+ UserState = verify_fun(OtpCert, {extension, Ext},
+ UserState0, VerifyFun),
+ validate_extensions(OtpCert,Rest, ValidationState, ExistBasicCon,
+ SelfSigned, UserState, VerifyFun);
+
+validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-certificatePolicies',
+ extnValue = #'PolicyInformation'{
+ policyIdentifier = Id,
+ policyQualifiers = Qualifier}}
+ | Rest], #path_validation_state{valid_policy_tree = Tree}
= ValidationState,
- ExistBasicCon, SelfSigned, UnknownExtensions,
- Verify, AccErr) ->
+ ExistBasicCon, SelfSigned, UserState, VerifyFun) ->
%% TODO: Policy imp incomplete
NewTree = process_policy_tree(Id, Qualifier, Tree),
- validate_extensions(Rest,
+ validate_extensions(OtpCert, Rest,
ValidationState#path_validation_state{
valid_policy_tree = NewTree},
- ExistBasicCon, SelfSigned, UnknownExtensions,
- Verify, AccErr);
+ ExistBasicCon, SelfSigned, UserState, VerifyFun);
-validate_extensions([#'Extension'{extnID = ?'id-ce-policyConstraints',
- critical = true} | Rest], ValidationState,
- ExistBasicCon, SelfSigned, UnknownExtensions, Verify,
- AccErr0) ->
+validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-policyConstraints',
+ critical = true} = Ext | Rest], ValidationState,
+ ExistBasicCon, SelfSigned, UserState0, VerifyFun) ->
%% TODO: Remove this clause when policy handling is
%% fully implemented
- AccErr =
- not_valid({bad_cert, unknown_critical_extension}, Verify, AccErr0),
- validate_extensions(Rest, ValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify, AccErr);
-validate_extensions([#'Extension'{extnID = ?'id-ce-policyConstraints',
- extnValue = #'PolicyConstraints'{
- requireExplicitPolicy = ExpPolicy,
- inhibitPolicyMapping = MapPolicy}}
- | Rest], ValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify, AccErr) ->
+ UserState = verify_fun(OtpCert, {extension, Ext},
+ UserState0, VerifyFun),
+ validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon,
+ SelfSigned, UserState, VerifyFun);
+validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-policyConstraints',
+ extnValue = #'PolicyConstraints'{
+ requireExplicitPolicy = ExpPolicy,
+ inhibitPolicyMapping = MapPolicy}}
+ | Rest], ValidationState, ExistBasicCon,
+ SelfSigned, UserState, VerifyFun) ->
%% TODO: Policy imp incomplete
- NewValidationState = add_policy_constraints(ExpPolicy, MapPolicy,
+ NewValidationState = add_policy_constraints(ExpPolicy, MapPolicy,
ValidationState),
- validate_extensions(Rest, NewValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify, AccErr);
+ validate_extensions(OtpCert, Rest, NewValidationState, ExistBasicCon,
+ SelfSigned, UserState, VerifyFun);
-validate_extensions([Extension | Rest], ValidationState,
- ExistBasicCon, SelfSigned, UnknownExtensions,
- Verify, AccErr) ->
- validate_extensions(Rest, ValidationState, ExistBasicCon, SelfSigned,
- [Extension | UnknownExtensions], Verify, AccErr).
+validate_extensions(OtpCert, [#'Extension'{} = Extension | Rest],
+ ValidationState, ExistBasicCon,
+ SelfSigned, UserState0, VerifyFun) ->
+ UserState = verify_fun(OtpCert, {extension, Extension}, UserState0, VerifyFun),
+ validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon, SelfSigned,
+ UserState, VerifyFun).
is_valid_key_usage(KeyUse, Use) ->
lists:member(Use, KeyUse).
validate_subject_alt_names([]) ->
- true;
+ false;
validate_subject_alt_names([AltName | Rest]) ->
case is_valid_subject_alt_name(AltName) of
true ->
- validate_subject_alt_names(Rest);
+ true;
false ->
- false
+ validate_subject_alt_names(Rest)
end.
is_valid_subject_alt_name({Name, Value}) when Name == rfc822Name;
@@ -600,14 +677,11 @@ is_valid_subject_alt_name({directoryName, _}) ->
true;
is_valid_subject_alt_name({_, [_|_]}) ->
true;
+is_valid_subject_alt_name({otherName, #'AnotherName'{}}) ->
+ false;
is_valid_subject_alt_name({_, _}) ->
false.
-min(N, M) when N =< M ->
- N;
-min(_, M) ->
- M.
-
is_ip_address(Address) ->
case inet_parse:address(Address) of
{ok, _} ->
@@ -670,10 +744,11 @@ split_auth_path(URIPart) ->
end.
split_uri(UriPart, SplitChar, NoMatchResult, SkipLeft, SkipRight) ->
- case regexp:first_match(UriPart, SplitChar) of
- {match, Match, _} ->
- {string:substr(UriPart, 1, Match - SkipLeft),
- string:substr(UriPart, Match + SkipRight, length(UriPart))};
+ case re:run(UriPart, SplitChar) of
+ {match,[{Start, _}]} ->
+ StrPos = Start + 1,
+ {string:substr(UriPart, 1, StrPos - SkipLeft),
+ string:substr(UriPart, StrPos + SkipRight, length(UriPart))};
nomatch ->
NoMatchResult
end.
@@ -926,7 +1001,7 @@ add_policy_constraints(ExpPolicy, MapPolicy,
policy_constraint(Current, asn1_NOVALUE, _) ->
Current;
policy_constraint(Current, New, CertNum) ->
- min(Current, New + CertNum).
+ erlang:min(Current, New + CertNum).
process_policy_tree(_,_, ?NULL) ->
?NULL;
diff --git a/lib/public_key/src/pubkey_cert_records.erl b/lib/public_key/src/pubkey_cert_records.erl
index ac04e1c2cb..20b322b4a4 100644
--- a/lib/public_key/src/pubkey_cert_records.erl
+++ b/lib/public_key/src/pubkey_cert_records.erl
@@ -23,30 +23,61 @@
-include("public_key.hrl").
--export([decode_cert/2, encode_cert/1, encode_tbs_cert/1, transform/2]).
+-export([decode_cert/1, transform/2]).
%%====================================================================
%% Internal application API
%%====================================================================
-decode_cert(DerCert, plain) ->
- 'OTP-PUB-KEY':decode('Certificate', DerCert);
-decode_cert(DerCert, otp) ->
+%%--------------------------------------------------------------------
+-spec decode_cert(der_encoded()) -> {ok, #'OTPCertificate'{}}.
+%%
+%% Description: Recursively decodes a Certificate.
+%%--------------------------------------------------------------------
+decode_cert(DerCert) ->
{ok, Cert} = 'OTP-PUB-KEY':decode('OTPCertificate', DerCert),
#'OTPCertificate'{tbsCertificate = TBS} = Cert,
{ok, Cert#'OTPCertificate'{tbsCertificate = decode_tbs(TBS)}}.
-encode_cert(Cert = #'Certificate'{}) ->
- {ok, EncCert} = 'OTP-PUB-KEY':encode('Certificate', Cert),
- list_to_binary(EncCert);
-encode_cert(C = #'OTPCertificate'{tbsCertificate = TBS}) ->
- Cert = C#'OTPCertificate'{tbsCertificate=encode_tbs(TBS)},
- {ok, EncCert} = 'OTP-PUB-KEY':encode('OTPCertificate', Cert),
- list_to_binary(EncCert).
-
-encode_tbs_cert(TBS) ->
- {ok, EncTBSCert} = 'OTP-PUB-KEY':encode('OTPTBSCertificate', encode_tbs(TBS)),
- list_to_binary(EncTBSCert).
+%%--------------------------------------------------------------------
+-spec transform(term(), encode | decode) ->term().
+%%
+%% Description: Transforms between encoded and decode otp formated
+%% certificate parts.
+%%--------------------------------------------------------------------
+
+transform(#'OTPCertificate'{tbsCertificate = TBS} = Cert, encode) ->
+ Cert#'OTPCertificate'{tbsCertificate=encode_tbs(TBS)};
+transform(#'OTPCertificate'{tbsCertificate = TBS} = Cert, decode) ->
+ Cert#'OTPCertificate'{tbsCertificate=decode_tbs(TBS)};
+transform(#'OTPTBSCertificate'{}= TBS, encode) ->
+ encode_tbs(TBS);
+transform(#'OTPTBSCertificate'{}= TBS, decode) ->
+ decode_tbs(TBS);
+transform(#'AttributeTypeAndValue'{type=Id,value=Value0} = ATAV, Func) ->
+ {ok, Value} =
+ case attribute_type(Id) of
+ Type when is_atom(Type) -> 'OTP-PUB-KEY':Func(Type, Value0);
+ _UnknownType -> {ok, Value0}
+ end,
+ ATAV#'AttributeTypeAndValue'{value=Value};
+transform(AKI = #'AuthorityKeyIdentifier'{authorityCertIssuer=ACI},Func) ->
+ AKI#'AuthorityKeyIdentifier'{authorityCertIssuer=transform(ACI,Func)};
+transform(List = [{directoryName, _}],Func) ->
+ [{directoryName, transform(Value,Func)} || {directoryName, Value} <- List];
+transform({directoryName, Value},Func) ->
+ {directoryName, transform(Value,Func)};
+transform({rdnSequence, SeqList},Func) when is_list(SeqList) ->
+ {rdnSequence,
+ lists:map(fun(Seq) ->
+ lists:map(fun(Element) -> transform(Element,Func) end, Seq)
+ end, SeqList)};
+transform(#'NameConstraints'{permittedSubtrees=Permitted, excludedSubtrees=Excluded}, Func) ->
+ #'NameConstraints'{permittedSubtrees=transform_sub_tree(Permitted,Func),
+ excludedSubtrees=transform_sub_tree(Excluded,Func)};
+
+transform(Other,_) ->
+ Other.
%%--------------------------------------------------------------------
%%% Internal functions
@@ -132,31 +163,6 @@ encode_extensions(Exts) ->
end
end, Exts).
-transform(#'AttributeTypeAndValue'{type=Id,value=Value0} = ATAV, Func) ->
- {ok, Value} =
- case attribute_type(Id) of
- Type when is_atom(Type) -> 'OTP-PUB-KEY':Func(Type, Value0);
- _UnknownType -> {ok, Value0}
- end,
- ATAV#'AttributeTypeAndValue'{value=Value};
-transform(AKI = #'AuthorityKeyIdentifier'{authorityCertIssuer=ACI},Func) ->
- AKI#'AuthorityKeyIdentifier'{authorityCertIssuer=transform(ACI,Func)};
-transform(List = [{directoryName, _}],Func) ->
- [{directoryName, transform(Value,Func)} || {directoryName, Value} <- List];
-transform({directoryName, Value},Func) ->
- {directoryName, transform(Value,Func)};
-transform({rdnSequence, SeqList},Func) when is_list(SeqList) ->
- {rdnSequence,
- lists:map(fun(Seq) ->
- lists:map(fun(Element) -> transform(Element,Func) end, Seq)
- end, SeqList)};
-transform(#'NameConstraints'{permittedSubtrees=Permitted, excludedSubtrees=Excluded}, Func) ->
- #'NameConstraints'{permittedSubtrees=transform_sub_tree(Permitted,Func),
- excludedSubtrees=transform_sub_tree(Excluded,Func)};
-
-transform(Other,_) ->
- Other.
-
encode_tbs(TBS=#'OTPTBSCertificate'{issuer=Issuer0,
subject=Subject0,
subjectPublicKeyInfo=Spki0,
diff --git a/lib/public_key/src/pubkey_crypto.erl b/lib/public_key/src/pubkey_crypto.erl
deleted file mode 100644
index 7b7abb1c56..0000000000
--- a/lib/public_key/src/pubkey_crypto.erl
+++ /dev/null
@@ -1,171 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-%% Description: Functions that call the crypto driver.
-
--module(pubkey_crypto).
-
--include("public_key.hrl").
-
--export([encrypt_public/3, decrypt_private/3,
- encrypt_private/3, decrypt_public/3,
- sign/2, sign/3, verify/5, gen_key/2]).
-
--define(UINT32(X), X:32/unsigned-big-integer).
-
-%%====================================================================
-%% Internal application API
-%%====================================================================
-
-%%--------------------------------------------------------------------
-%% Function: encrypt(PlainText, Key, Padding) -> Encrypted
-%%
-%% PlainText = binary()
-%% Key = rsa_public_key() | rsa_private_key()
-%% Padding = rsa_pkcs1_padding | rsa_pkcs1_oaep_padding
-%% Encrypted = binary()
-%%
-%% Description: Public key encrypts PlainText.
-%%--------------------------------------------------------------------
-encrypt_public(PlainText, #'RSAPublicKey'{modulus=N,publicExponent=E},
- Padding) ->
- crypto:rsa_public_encrypt(PlainText, [crypto:mpint(E),crypto:mpint(N)],
- Padding);
-encrypt_public(PlainText, #'RSAPrivateKey'{modulus=N,publicExponent=E},
- Padding) ->
- crypto:rsa_public_encrypt(PlainText, [crypto:mpint(E),crypto:mpint(N)],
- Padding).
-
-encrypt_private(PlainText, #'RSAPrivateKey'{modulus = N,
- publicExponent = E,
- privateExponent = D}, Padding) ->
- crypto:rsa_private_encrypt(PlainText, [crypto:mpint(E),
- crypto:mpint(N),
- crypto:mpint(D)], Padding).
-
-%%--------------------------------------------------------------------
-%% Function: decrypt(CipherText, Key) -> PlainText
-%%
-%% ChipherText = binary()
-%% Key = rsa_private_key()
-%% Padding = rsa_pkcs1_padding | rsa_pkcs1_oaep_padding
-%% PlainText = binary()
-%%
-%% Description: Uses private key to decrypt public key encrypted data.
-%%--------------------------------------------------------------------
-decrypt_private(CipherText,
- #'RSAPrivateKey'{modulus = N,publicExponent = E,
- privateExponent = D},
- Padding) ->
- crypto:rsa_private_decrypt(CipherText,
- [crypto:mpint(E), crypto:mpint(N),
- crypto:mpint(D)], Padding).
-decrypt_public(CipherText, #'RSAPublicKey'{modulus = N, publicExponent = E},
- Padding) ->
- crypto:rsa_public_decrypt(CipherText,[crypto:mpint(E), crypto:mpint(N)],
- Padding);
-decrypt_public(CipherText, #'RSAPrivateKey'{modulus = N, publicExponent = E},
- Padding) ->
- crypto:rsa_public_decrypt(CipherText,[crypto:mpint(E), crypto:mpint(N)],
- Padding).
-
-%%--------------------------------------------------------------------
-%% Function: sign(PlainText, Key) ->
-%% sign(DigestType, PlainText, Key) -> Signature
-%%
-%% DigestType = sha | md5
-%% PlainText = binary()
-%% Key = rsa_private_key() | dsa_private_key()
-%% Signature = binary()
-%%
-%% Description: Signs PlainText using Key.
-%%--------------------------------------------------------------------
-sign(PlainText, Digest) ->
- sign(sha, PlainText, Digest).
-
-sign(DigestType, PlainText, #'RSAPrivateKey'{modulus = N, publicExponent = E,
- privateExponent = D}) ->
- crypto:rsa_sign(DigestType, sized_binary(PlainText), [crypto:mpint(E),
- crypto:mpint(N),
- crypto:mpint(D)]);
-
-sign(none, Hash, #'DSAPrivateKey'{p = P, q = Q, g = G, x = X}) ->
- crypto:dss_sign(none, Hash,
- [crypto:mpint(P), crypto:mpint(Q),
- crypto:mpint(G), crypto:mpint(X)]);
-
-sign(sha, PlainText, #'DSAPrivateKey'{p = P, q = Q, g = G, x = X}) ->
- crypto:dss_sign(sized_binary(PlainText),
- [crypto:mpint(P), crypto:mpint(Q),
- crypto:mpint(G), crypto:mpint(X)]).
-
-%%--------------------------------------------------------------------
-%% Function: verify(DigestType, PlainText, Signature, Key) -> true | false
-%%
-%% DigestType = sha | md5
-%% PlainText = binary()
-%% Signature = binary()
-%% Key = rsa_public_key() | dsa_public_key()
-%%
-%% Description: Verifies the signature <Signature>.
-%%--------------------------------------------------------------------
-verify(DigestType, PlainText, Signature,
- #'RSAPublicKey'{modulus = Mod, publicExponent = Exp}, _) ->
- crypto:rsa_verify(DigestType,
- sized_binary(PlainText),
- sized_binary(Signature),
- [crypto:mpint(Exp), crypto:mpint(Mod)]);
-
-verify(none, Hash, Signature, Key, #'Dss-Parms'{p = P, q = Q, g = G}) ->
- crypto:dss_verify(none, Hash,
- sized_binary(Signature),
- [crypto:mpint(P), crypto:mpint(Q),
- crypto:mpint(G), crypto:mpint(Key)]);
-
-verify(sha, PlainText, Signature, Key, #'Dss-Parms'{p = P, q = Q, g = G}) ->
- crypto:dss_verify(sized_binary(PlainText),
- sized_binary(Signature),
- [crypto:mpint(P), crypto:mpint(Q),
- crypto:mpint(G), crypto:mpint(Key)]).
-
-
-%%--------------------------------------------------------------------
-%% Function: gen_key(Type, Params) ->
-%% Type = diffie_hellman
-%% Params = [P,G] | [Y, P, G]
-%% Description: Generates keys.
-%% -----------------------------------------------------------------
-gen_key(diffie_hellman, [Y, P, G]) ->
- crypto:dh_generate_key(crypto:mpint(Y), [crypto:mpint(P),
- crypto:mpint(G)]);
-gen_key(diffie_hellman, [P, G]) ->
- crypto:dh_generate_key([crypto:mpint(P), crypto:mpint(G)]).
-
-%%% TODO: Support rsa, dss key_gen
-
-%%--------------------------------------------------------------------
-%%% Internal functions
-%%--------------------------------------------------------------------
-sized_binary(Binary) when is_binary(Binary) ->
- Size = size(Binary),
- <<?UINT32(Size), Binary/binary>>;
-sized_binary(List) ->
- sized_binary(list_to_binary(List)).
-
diff --git a/lib/public_key/src/pubkey_pem.erl b/lib/public_key/src/pubkey_pem.erl
index 65879f1bbe..31d881973a 100644
--- a/lib/public_key/src/pubkey_pem.erl
+++ b/lib/public_key/src/pubkey_pem.erl
@@ -40,7 +40,10 @@
-module(pubkey_pem).
--export([read_file/1, read_file/2, write_file/2, decode/2]).
+-include("public_key.hrl").
+
+-export([encode/1, decode/1, decipher/2, cipher/3]).
+%% Backwards compatibility
-export([decode_key/2]).
-define(ENCODED_LINE_LENGTH, 64).
@@ -48,28 +51,82 @@
%%====================================================================
%% Internal application API
%%====================================================================
-read_file(File) ->
- read_file(File, no_passwd).
-read_file(File, Passwd) ->
- {ok, Bin} = file:read_file(File),
- decode(Bin, Passwd).
+%%--------------------------------------------------------------------
+-spec decode(binary()) -> [pem_entry()].
+%%
+%% Description: Decodes a PEM binary.
+%%--------------------------------------------------------------------
+decode(Bin) ->
+ decode_pem_entries(split_bin(Bin), []).
-write_file(File, Ds) ->
- file:write_file(File, encode_file(Ds)).
+%%--------------------------------------------------------------------
+-spec encode([pem_entry()]) -> iolist().
+%%
+%% Description: Encodes a list of PEM entries.
+%%--------------------------------------------------------------------
+encode(PemEntries) ->
+ encode_pem_entries(PemEntries).
-decode_key({_Type, Bin, not_encrypted}, _) ->
- Bin;
-decode_key({_Type, Bin, {Chipher,Salt}}, Password) ->
- decode_key(Bin, Password, Chipher, Salt).
+%%--------------------------------------------------------------------
+-spec decipher({pki_asn1_type(), decrypt_der(),{Cipher :: string(), Salt :: binary()}}, string()) ->
+ der_encoded().
+%%
+%% Description: Deciphers a decrypted pem entry.
+%%--------------------------------------------------------------------
+decipher({_, DecryptDer, {Cipher,Salt}}, Password) ->
+ decode_key(DecryptDer, Password, Cipher, Salt).
-decode(Bin, Passwd) ->
- decode_file(split_bin(Bin), Passwd).
+%%--------------------------------------------------------------------
+-spec cipher(der_encoded(),{Cipher :: string(), Salt :: binary()} , string()) -> binary().
+%%
+%% Description: Ciphers a PEM entry
+%%--------------------------------------------------------------------
+cipher(Der, {Cipher,Salt}, Password)->
+ encode_key(Der, Password, Cipher, Salt).
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
+encode_pem_entries(Entries) ->
+ [encode_pem_entry(Entry) || Entry <- Entries].
+
+encode_pem_entry({Asn1Type, Der, not_encrypted}) ->
+ StartStr = pem_start(Asn1Type),
+ [StartStr, "\n", b64encode_and_split(Der), pem_end(StartStr) ,"\n\n"];
+encode_pem_entry({Asn1Type, Der, {Cipher, Salt}}) ->
+ StartStr = pem_start(Asn1Type),
+ [StartStr,"\n", pem_decrypt(),"\n", pem_decrypt_info(Cipher, Salt),"\n",
+ b64encode_and_split(Der), pem_end(StartStr) ,"\n\n"].
+
+decode_pem_entries([], Entries) ->
+ lists:reverse(Entries);
+decode_pem_entries([<<>>], Entries) ->
+ lists:reverse(Entries);
+decode_pem_entries([<<>> | Lines], Entries) ->
+ decode_pem_entries(Lines, Entries);
+decode_pem_entries([Start| Lines], Entries) ->
+ case pem_end(Start) of
+ undefined ->
+ decode_pem_entries(Lines, Entries);
+ _End ->
+ {Entry, RestLines} = join_entry(Lines, []),
+ decode_pem_entries(RestLines, [decode_pem_entry(Start, Entry) | Entries])
+ end.
+decode_pem_entry(Start, [<<"Proc-Type: 4,ENCRYPTED", _/binary>>, Line | Lines]) ->
+ Asn1Type = asn1_type(Start),
+ Cs = erlang:iolist_to_binary(Lines),
+ Decoded = base64:mime_decode(Cs),
+ [_, DekInfo0] = string:tokens(binary_to_list(Line), ": "),
+ [Cipher, Salt] = string:tokens(DekInfo0, ","),
+ {Asn1Type, Decoded, {Cipher, unhex(Salt)}};
+decode_pem_entry(Start, Lines) ->
+ Asn1Type = asn1_type(Start),
+ Cs = erlang:iolist_to_binary(Lines),
+ Der = base64:mime_decode(Cs),
+ {Asn1Type, Der, not_encrypted}.
+
split_bin(Bin) ->
split_bin(0, Bin).
@@ -85,88 +142,26 @@ split_bin(N, Bin) ->
split_bin(N+1, Bin)
end.
-decode_file(Bin, Passwd) ->
- decode_file(Bin, [], [Passwd]).
-
-decode_file([<<"-----BEGIN CERTIFICATE REQUEST-----", _/binary>>|Rest], Ens, Info) ->
- decode_file2(Rest, [], Ens, cert_req, Info);
-decode_file([<<"-----BEGIN CERTIFICATE-----", _/binary>>|Rest], Ens, Info) ->
- decode_file2(Rest, [], Ens, cert, Info);
-decode_file([<<"-----BEGIN RSA PRIVATE KEY-----", _/binary>>|Rest], Ens, Info) ->
- decode_file2(Rest, [], Ens, rsa_private_key, Info);
-decode_file([<<"-----BEGIN DSA PRIVATE KEY-----", _/binary>>|Rest], Ens, Info) ->
- decode_file2(Rest, [], Ens, dsa_private_key, Info);
-decode_file([<<"-----BEGIN DH PARAMETERS-----", _/binary>>|Rest], Ens, Info) ->
- decode_file2(Rest, [], Ens, dh_params, Info);
-decode_file([_|Rest], Ens, Info) ->
- decode_file(Rest, Ens, Info);
-decode_file([], Ens, _Info) ->
- {ok, lists:reverse(Ens)}.
-
-decode_file2([<<"Proc-Type: 4,ENCRYPTED", _/binary>>| Rest0], RLs, Ens, Tag, Info0) ->
- [InfoLine|Rest] = Rest0,
- Info = dek_info(InfoLine, Info0),
- decode_file2(Rest, RLs, Ens, Tag, Info);
-decode_file2([<<"-----END", _/binary>>| Rest], RLs, Ens, Tag, Info0) ->
- Cs = erlang:iolist_to_binary(lists:reverse(RLs)),
- Bin = base64:mime_decode(Cs),
- case Info0 of
- [Password, Cipher, SaltHex | Info1] ->
- Salt = unhex(SaltHex),
- Enc = {Cipher, Salt},
- Decoded = decode_key(Bin, Password, Cipher, Salt),
- decode_file(Rest, [{Tag, Decoded, Enc}| Ens], Info1);
- _ ->
- decode_file(Rest, [{Tag, Bin, not_encrypted}| Ens], Info0)
- end;
-decode_file2([L|Rest], RLs, Ens, Tag, Info0) ->
- decode_file2(Rest, [L|RLs], Ens, Tag, Info0);
-decode_file2([], _, Ens, _, _) ->
- {ok, lists:reverse(Ens)}.
-
-%% Support same as decode_file
-encode_file(Ds) ->
- lists:map(
- fun({cert, Bin, not_encrypted}) ->
- %% PKIX (X.509)
- ["-----BEGIN CERTIFICATE-----\n",
- b64encode_and_split(Bin),
- "-----END CERTIFICATE-----\n\n"];
- ({cert_req, Bin, not_encrypted}) ->
- %% PKCS#10
- ["-----BEGIN CERTIFICATE REQUEST-----\n",
- b64encode_and_split(Bin),
- "-----END CERTIFICATE REQUEST-----\n\n"];
- ({rsa_private_key, Bin, not_encrypted}) ->
- %% PKCS#?
- ["XXX Following key assumed not encrypted\n",
- "-----BEGIN RSA PRIVATE KEY-----\n",
- b64encode_and_split(Bin),
- "-----END RSA PRIVATE KEY-----\n\n"];
- ({dsa_private_key, Bin, not_encrypted}) ->
- %% PKCS#?
- ["XXX Following key assumed not encrypted\n",
- "-----BEGIN DSA PRIVATE KEY-----\n",
- b64encode_and_split(Bin),
- "-----END DSA PRIVATE KEY-----\n\n"]
- end, Ds).
-
-dek_info(Line0, Info) ->
- Line = binary_to_list(Line0),
- [_, DekInfo0] = string:tokens(Line, ": "),
- DekInfo1 = string:tokens(DekInfo0, ",\n"),
- Info ++ DekInfo1.
+b64encode_and_split(Bin) ->
+ split_lines(base64:encode(Bin)).
-unhex(S) ->
- unhex(S, []).
+split_lines(<<Text:?ENCODED_LINE_LENGTH/binary, Rest/binary>>) ->
+ [Text, $\n | split_lines(Rest)];
+split_lines(Bin) ->
+ [Bin, $\n].
-unhex("", Acc) ->
- list_to_binary(lists:reverse(Acc));
-unhex([D1, D2 | Rest], Acc) ->
- unhex(Rest, [erlang:list_to_integer([D1, D2], 16) | Acc]).
+%% Ignore white space at end of line
+join_entry([<<"-----END CERTIFICATE-----", _/binary>>| Lines], Entry) ->
+ {lists:reverse(Entry), Lines};
+join_entry([<<"-----END RSA PRIVATE KEY-----", _/binary>>| Lines], Entry) ->
+ {lists:reverse(Entry), Lines};
+join_entry([<<"-----END DSA PRIVATE KEY-----", _/binary>>| Lines], Entry) ->
+ {lists:reverse(Entry), Lines};
+join_entry([<<"-----END DH PARAMETERS-----", _/binary>>| Lines], Entry) ->
+ {lists:reverse(Entry), Lines};
+join_entry([Line | Lines], Entry) ->
+ join_entry(Lines, [Line | Entry]).
-decode_key(Data, no_passwd, _Alg, _Salt) ->
- Data;
decode_key(Data, Password, "DES-CBC", Salt) ->
Key = password_to_key(Password, Salt, 8),
IV = Salt,
@@ -177,6 +172,16 @@ decode_key(Data, Password, "DES-EDE3-CBC", Salt) ->
<<Key1:8/binary, Key2:8/binary, Key3:8/binary>> = Key,
crypto:des_ede3_cbc_decrypt(Key1, Key2, Key3, IV, Data).
+encode_key(Data, Password, "DES-CBC", Salt) ->
+ Key = password_to_key(Password, Salt, 8),
+ IV = Salt,
+ crypto:des_cbc_encrypt(Key, IV, Data);
+encode_key(Data, Password, "DES-EDE3-CBC", Salt) ->
+ Key = password_to_key(Password, Salt, 24),
+ IV = Salt,
+ <<Key1:8/binary, Key2:8/binary, Key3:8/binary>> = Key,
+ crypto:des_ede3_cbc_encrypt(Key1, Key2, Key3, IV, Data).
+
password_to_key(Data, Salt, KeyLen) ->
<<Key:KeyLen/binary, _/binary>> =
password_to_key(<<>>, Data, Salt, KeyLen, <<>>),
@@ -188,11 +193,58 @@ password_to_key(Prev, Data, Salt, Len, Acc) ->
M = crypto:md5([Prev, Data, Salt]),
password_to_key(M, Data, Salt, Len - size(M), <<Acc/binary, M/binary>>).
-b64encode_and_split(Bin) ->
- split_lines(base64:encode(Bin)).
+unhex(S) ->
+ unhex(S, []).
-split_lines(<<Text:?ENCODED_LINE_LENGTH/binary, Rest/binary>>) ->
- [Text, $\n | split_lines(Rest)];
-split_lines(Bin) ->
- [Bin, $\n].
+unhex("", Acc) ->
+ list_to_binary(lists:reverse(Acc));
+unhex([D1, D2 | Rest], Acc) ->
+ unhex(Rest, [erlang:list_to_integer([D1, D2], 16) | Acc]).
+
+hexify(L) -> [[hex_byte(B)] || B <- binary_to_list(L)].
+
+hex_byte(B) when B < 16#10 -> ["0", erlang:integer_to_list(B, 16)];
+hex_byte(B) -> erlang:integer_to_list(B, 16).
+
+pem_start('Certificate') ->
+ <<"-----BEGIN CERTIFICATE-----">>;
+pem_start('RSAPrivateKey') ->
+ <<"-----BEGIN RSA PRIVATE KEY-----">>;
+pem_start('DSAPrivateKey') ->
+ <<"-----BEGIN DSA PRIVATE KEY-----">>;
+pem_start('DHParameter') ->
+ <<"-----BEGIN DH PARAMETERS-----">>.
+
+pem_end(<<"-----BEGIN CERTIFICATE-----">>) ->
+ <<"-----END CERTIFICATE-----">>;
+pem_end(<<"-----BEGIN RSA PRIVATE KEY-----">>) ->
+ <<"-----END RSA PRIVATE KEY-----">>;
+pem_end(<<"-----BEGIN DSA PRIVATE KEY-----">>) ->
+ <<"-----END DSA PRIVATE KEY-----">>;
+pem_end(<<"-----BEGIN DH PARAMETERS-----">>) ->
+ <<"-----END DH PARAMETERS-----">>;
+pem_end(_) ->
+ undefined.
+
+asn1_type(<<"-----BEGIN CERTIFICATE-----">>) ->
+ 'Certificate';
+asn1_type(<<"-----BEGIN RSA PRIVATE KEY-----">>) ->
+ 'RSAPrivateKey';
+asn1_type(<<"-----BEGIN DSA PRIVATE KEY-----">>) ->
+ 'DSAPrivateKey';
+asn1_type(<<"-----BEGIN DH PARAMETERS-----">>) ->
+ 'DHParameter'.
+
+pem_decrypt() ->
+ <<"Proc-Type: 4,ENCRYPTED">>.
+
+pem_decrypt_info(Cipher, Salt) ->
+ io_lib:format("DEK-Info: ~s,~s", [Cipher, lists:flatten(hexify(Salt))]).
+%%--------------------------------------------------------------------
+%%% Deprecated
+%%--------------------------------------------------------------------
+decode_key({_Type, Bin, not_encrypted}, _) ->
+ Bin;
+decode_key({_Type, Bin, {Chipher,Salt}}, Password) ->
+ decode_key(Bin, Password, Chipher, Salt).
diff --git a/lib/public_key/src/public_key.app.src b/lib/public_key/src/public_key.app.src
index d5e1705827..60487946fa 100644
--- a/lib/public_key/src/public_key.app.src
+++ b/lib/public_key/src/public_key.app.src
@@ -4,7 +4,6 @@
{modules, [
public_key,
pubkey_pem,
- pubkey_crypto,
pubkey_cert,
pubkey_cert_records,
'OTP-PUB-KEY'
diff --git a/lib/public_key/src/public_key.appup.src b/lib/public_key/src/public_key.appup.src
index 2eb5750923..0f9f62d2f6 100644
--- a/lib/public_key/src/public_key.appup.src
+++ b/lib/public_key/src/public_key.appup.src
@@ -1,44 +1,24 @@
%% -*- erlang -*-
{"%VSN%",
[
- {"0.6",
+ {"0.8",
[
{update, 'OTP-PUB-KEY', soft, soft_purge, soft_purge, []},
{update, public_key, soft, soft_purge, soft_purge, []},
{update, pubkey_pem, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert_records, soft, soft_purge, soft_purge, []}
- {update, pubkey_cert, soft, soft_purge, soft_purge, []}
- ]
- },
- {"0.5",
- [
- {update, 'OTP-PUB-KEY', soft, soft_purge, soft_purge, []},
- {update, public_key, soft, soft_purge, soft_purge, []},
- {update, pubkey_crypto, soft, soft_purge, soft_purge, []},
- {update, pubkey_pem, soft, soft_purge, soft_purge, []},
{update, pubkey_cert_records, soft, soft_purge, soft_purge, []},
{update, pubkey_cert, soft, soft_purge, soft_purge, []}
]
}
],
[
- {"0.6",
+ {"0.8",
[
{update, 'OTP-PUB-KEY', soft, soft_purge, soft_purge, []},
{update, public_key, soft, soft_purge, soft_purge, []},
{update, pubkey_pem, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert_records, soft, soft_purge, soft_purge, []}
- {update, pubkey_cert, soft, soft_purge, soft_purge, []}
- ]
- },
- {"0.5",
- [
- {update, 'OTP-PUB-KEY', soft, soft_purge, soft_purge, []},
- {update, public_key, soft, soft_purge, soft_purge, []},
- {update, pubkey_crypto, soft, soft_purge, soft_purge, []},
- {update, pubkey_pem, soft, soft_purge, soft_purge, []},
{update, pubkey_cert_records, soft, soft_purge, soft_purge, []},
{update, pubkey_cert, soft, soft_purge, soft_purge, []}
]
- }
+ }
]}.
diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl
index 12354eee5d..095a6ff0e0 100644
--- a/lib/public_key/src/public_key.erl
+++ b/lib/public_key/src/public_key.erl
@@ -23,239 +23,395 @@
-include("public_key.hrl").
--export([decode_private_key/1, decode_private_key/2, decode_dhparams/1,
- decrypt_private/2, decrypt_private/3, encrypt_public/2,
- encrypt_public/3, decrypt_public/2, decrypt_public/3,
- encrypt_private/2, encrypt_private/3, gen_key/1, sign/2, sign/3,
- verify_signature/3, verify_signature/4, verify_signature/5,
- pem_to_der/1, pem_to_der/2, der_to_pem/2,
- pkix_decode_cert/2, pkix_encode_cert/1, pkix_transform/2,
- pkix_is_self_signed/1, pkix_is_fixed_dh_cert/1,
+-export([pem_decode/1, pem_encode/1,
+ der_decode/2, der_encode/2,
+ pem_entry_decode/1,
+ pem_entry_decode/2,
+ pem_entry_encode/2,
+ pem_entry_encode/3,
+ pkix_decode_cert/2, pkix_encode/3,
+ encrypt_private/2, encrypt_private/3,
+ decrypt_private/2, decrypt_private/3,
+ encrypt_public/2, encrypt_public/3,
+ decrypt_public/2, decrypt_public/3,
+ sign/3, verify/4,
+ pkix_sign/2, pkix_verify/2,
+ pkix_is_self_signed/1,
+ pkix_is_fixed_dh_cert/1,
+ pkix_is_issuer/2,
pkix_issuer_id/2,
- pkix_is_issuer/2, pkix_normalize_general_name/1,
+ pkix_normalize_name/1,
pkix_path_validation/3
]).
+%% Deprecated
+-export([decode_private_key/1, decode_private_key/2, pem_to_der/1]).
+
+-deprecated({pem_to_der, 1, next_major_release}).
+-deprecated({decode_private_key, 1, next_major_release}).
+-deprecated({decode_private_key, 2, next_major_release}).
+
+-type rsa_public_key() :: #'RSAPublicKey'{}.
+-type rsa_private_key() :: #'RSAPrivateKey'{}.
+-type dsa_private_key() :: #'DSAPrivateKey'{}.
+-type dsa_public_key() :: {integer(), #'Dss-Parms'{}}.
+-type rsa_padding() :: 'rsa_pkcs1_padding' | 'rsa_pkcs1_oaep_padding'
+ | 'rsa_no_padding'.
+-type public_crypt_options() :: [{rsa_pad, rsa_padding()}].
+-type rsa_digest_type() :: 'md5' | 'sha'.
+-type dss_digest_type() :: 'none' | 'sha'.
+
+-define(UINT32(X), X:32/unsigned-big-integer).
+
%%====================================================================
%% API
%%====================================================================
%%--------------------------------------------------------------------
-%% Function: decode_private_key(KeyInfo [,Password]) ->
-%% {ok, PrivateKey} | {error, Reason}
-%%
-%% KeyInfo = {Type, der_bin(), ChipherInfo} - as returned from
-%% pem_to_der/[1,2] for private keys
-%% Type = rsa_private_key | dsa_private_key
-%% ChipherInfo = opaque() | no_encryption
+-spec pem_decode(binary()) -> [pem_entry()].
+%%
+%% Description: Decode PEM binary data and return
+%% entries as asn1 der encoded entities.
+%%--------------------------------------------------------------------
+pem_decode(PemBin) when is_binary(PemBin) ->
+ pubkey_pem:decode(PemBin).
+
+%%--------------------------------------------------------------------
+-spec pem_encode([pem_entry()]) -> binary().
%%
-%% Description: Decodes an asn1 der encoded private key.
+%% Description: Creates a PEM binary.
%%--------------------------------------------------------------------
-decode_private_key(KeyInfo) ->
- decode_private_key(KeyInfo, no_passwd).
+pem_encode(PemEntries) when is_list(PemEntries) ->
+ iolist_to_binary(pubkey_pem:encode(PemEntries)).
-decode_private_key(KeyInfo = {rsa_private_key, _, _}, Password) ->
- DerEncoded = pubkey_pem:decode_key(KeyInfo, Password),
- 'OTP-PUB-KEY':decode('RSAPrivateKey', DerEncoded);
-decode_private_key(KeyInfo = {dsa_private_key, _, _}, Password) ->
- DerEncoded = pubkey_pem:decode_key(KeyInfo, Password),
- 'OTP-PUB-KEY':decode('DSAPrivateKey', DerEncoded).
+%%--------------------------------------------------------------------
+-spec pem_entry_decode(pem_entry(), [string()]) -> term().
+%
+%% Description: Decodes a pem entry. pem_decode/1 returns a list of
+%% pem entries.
+%%--------------------------------------------------------------------
+pem_entry_decode({Asn1Type, Der, not_encrypted}) when is_atom(Asn1Type),
+ is_binary(Der) ->
+ der_decode(Asn1Type, Der).
+pem_entry_decode({Asn1Type, Der, not_encrypted}, _) when is_atom(Asn1Type),
+ is_binary(Der) ->
+ der_decode(Asn1Type, Der);
+pem_entry_decode({Asn1Type, CryptDer, {Cipher, Salt}} = PemEntry,
+ Password) when is_atom(Asn1Type),
+ is_binary(CryptDer),
+ is_list(Cipher),
+ is_binary(Salt),
+ erlang:byte_size(Salt) == 8
+ ->
+ Der = pubkey_pem:decipher(PemEntry, Password),
+ der_decode(Asn1Type, Der).
+%%--------------------------------------------------------------------
+-spec pem_entry_encode(pki_asn1_type(), term()) -> pem_entry().
+-spec pem_entry_encode(pki_asn1_type(), term(),
+ {{Cipher :: string(), Salt :: binary()}, string()}) ->
+ pem_entry().
+%
+%% Description: Creates a pem entry that can be feed to pem_encode/1.
+%%--------------------------------------------------------------------
+pem_entry_encode(Asn1Type, Entity) when is_atom(Asn1Type) ->
+ Der = der_encode(Asn1Type, Entity),
+ {Asn1Type, Der, not_encrypted}.
+pem_entry_encode(Asn1Type, Entity,
+ {{Cipher, Salt}= CipherInfo, Password}) when is_atom(Asn1Type),
+ is_list(Cipher),
+ is_binary(Salt),
+ erlang:byte_size(Salt) == 8,
+ is_list(Password)->
+ Der = der_encode(Asn1Type, Entity),
+ DecryptDer = pubkey_pem:cipher(Der, CipherInfo, Password),
+ {Asn1Type, DecryptDer, CipherInfo}.
%%--------------------------------------------------------------------
-%% Function: decode_dhparams(DhParamInfo) ->
-%% {ok, DhParams} | {error, Reason}
+-spec der_decode(asn1_type(), der_encoded()) -> term().
%%
-%% DhParamsInfo = {Type, der_bin(), ChipherInfo} - as returned from
-%% pem_to_der/[1,2] for DH parameters.
-%% Type = dh_params
-%% ChipherInfo = opaque() | no_encryption
-%%
-%% Description: Decodes an asn1 der encoded DH parameters.
+%% Description: Decodes a public key asn1 der encoded entity.
%%--------------------------------------------------------------------
-decode_dhparams({dh_params, DerEncoded, not_encrypted}) ->
- 'OTP-PUB-KEY':decode('DHParameter', DerEncoded).
+der_decode(Asn1Type, Der) when is_atom(Asn1Type), is_binary(Der) ->
+ try
+ {ok, Decoded} = 'OTP-PUB-KEY':decode(Asn1Type, Der),
+ Decoded
+ catch
+ error:{badmatch, {error, _}} = Error ->
+ erlang:error(Error)
+ end.
%%--------------------------------------------------------------------
-%% Function: decrypt_private(CipherText, Key) ->
-%% decrypt_private(CipherText, Key, Options) -> PlainTex
-%% decrypt_public(CipherText, Key) ->
-%% decrypt_public(CipherText, Key, Options) -> PlainTex
+-spec der_encode(asn1_type(), term()) -> der_encoded().
%%
-%% CipherText = binary()
-%% Key = rsa_key()
-%% PlainText = binary()
+%% Description: Encodes a public key entity with asn1 DER encoding.
+%%--------------------------------------------------------------------
+der_encode(Asn1Type, Entity) when is_atom(Asn1Type) ->
+ try
+ {ok, Encoded} = 'OTP-PUB-KEY':encode(Asn1Type, Entity),
+ iolist_to_binary(Encoded)
+ catch
+ error:{badmatch, {error, _}} = Error ->
+ erlang:error(Error)
+ end.
+
+%%--------------------------------------------------------------------
+-spec pkix_decode_cert(der_encoded(), plain | otp) ->
+ #'Certificate'{} | #'OTPCertificate'{}.
%%
-%% Description: Decrypts <CipherText>.
+%% Description: Decodes an asn1 der encoded pkix certificate. The otp
+%% option will use the customized asn1 specification OTP-PKIX.asn1 for
+%% decoding and also recursively decode most of the standard
+%% extensions.
+%% --------------------------------------------------------------------
+pkix_decode_cert(DerCert, plain) when is_binary(DerCert) ->
+ der_decode('Certificate', DerCert);
+pkix_decode_cert(DerCert, otp) when is_binary(DerCert) ->
+ try
+ {ok, #'OTPCertificate'{}= Cert} =
+ pubkey_cert_records:decode_cert(DerCert),
+ Cert
+ catch
+ error:{badmatch, {error, _}} = Error ->
+ erlang:error(Error)
+ end.
+
+%%--------------------------------------------------------------------
+-spec pkix_encode(asn1_type(), term(), otp | plain) -> der_encoded().
+%%
+%% Description: Der encodes a certificate or part of a certificate.
+%% This function must be used for encoding certificates or parts of certificates
+%% that are decoded with the otp format, whereas for the plain format this
+%% function will only call der_encode/2.
+%%--------------------------------------------------------------------
+pkix_encode(Asn1Type, Term, plain) when is_atom(Asn1Type) ->
+ der_encode(Asn1Type, Term);
+
+pkix_encode(Asn1Type, Term0, otp) when is_atom(Asn1Type) ->
+ Term = pubkey_cert_records:transform(Term0, encode),
+ der_encode(Asn1Type, Term).
+
+%%--------------------------------------------------------------------
+-spec decrypt_private(CipherText :: binary(), rsa_private_key()) ->
+ PlainText :: binary().
+-spec decrypt_private(CipherText :: binary(), rsa_private_key(),
+ public_crypt_options()) -> PlainText :: binary().
+%%
+%% Description: Public key decryption using the private key.
%%--------------------------------------------------------------------
decrypt_private(CipherText, Key) ->
decrypt_private(CipherText, Key, []).
-decrypt_private(CipherText, Key, Options) ->
- Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding),
- pubkey_crypto:decrypt_private(CipherText, Key, Padding).
-decrypt_public(CipherText, Key) ->
- decrypt_public(CipherText, Key, []).
-decrypt_public(CipherText, Key, Options) ->
+decrypt_private(CipherText,
+ #'RSAPrivateKey'{modulus = N,publicExponent = E,
+ privateExponent = D},
+ Options) when is_binary(CipherText),
+ is_list(Options) ->
Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding),
- pubkey_crypto:decrypt_public(CipherText, Key, Padding).
+ crypto:rsa_private_decrypt(CipherText,
+ [crypto:mpint(E), crypto:mpint(N),
+ crypto:mpint(D)], Padding).
%%--------------------------------------------------------------------
-%% Function: encrypt_public(PlainText, Key, Options) -> CipherText
-%% encrypt_private(PlainText, Key, Options) -> CipherText
-%%
-%% PlainText = iolist()
-%% Key = rsa_private_key()
-%% CipherText = binary()
+-spec decrypt_public(CipherText :: binary(), rsa_public_key()) ->
+ PlainText :: binary().
+-spec decrypt_public(CipherText :: binary(), rsa_public_key(),
+ public_crypt_options()) -> PlainText :: binary().
%%
-%% Description: Encrypts <Plain>
+%% Description: Public key decryption using the public key.
%%--------------------------------------------------------------------
-encrypt_public(PlainText, Key) ->
- encrypt_public(PlainText, Key, []).
-encrypt_public(PlainText, Key, Options) ->
- Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding),
- pubkey_crypto:encrypt_public(PlainText, Key, Padding).
+decrypt_public(CipherText, Key) ->
+ decrypt_public(CipherText, Key, []).
-encrypt_private(PlainText, Key) ->
- encrypt_private(PlainText, Key, []).
-encrypt_private(PlainText, Key, Options) ->
- Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding),
- pubkey_crypto:encrypt_private(PlainText, Key, Padding).
+decrypt_public(CipherText, #'RSAPublicKey'{modulus = N, publicExponent = E},
+ Options) when is_binary(CipherText), is_list(Options) ->
+ decrypt_public(CipherText, N,E, Options);
-%%--------------------------------------------------------------------
-%% Function: gen_key(Params) -> Keys
-%%
-%% Params = #'DomainParameters'{} - Currently only supported option
-%% Keys = {PublicDHKey = integer(), PrivateDHKey = integer()}
-%%
-%% Description: Generates keys. Currently supports Diffie-Hellman keys.
-%%--------------------------------------------------------------------
-gen_key(#'DHParameter'{prime = P, base = G}) when is_integer(P),
- is_integer(G) ->
- pubkey_crypto:gen_key(diffie_hellman, [P, G]).
+decrypt_public(CipherText,#'RSAPrivateKey'{modulus = N, publicExponent = E},
+ Options) when is_binary(CipherText), is_list(Options) ->
+ decrypt_public(CipherText, N,E, Options).
%%--------------------------------------------------------------------
-%% Function: pem_to_der(CertSource) ->
-%% pem_to_der(CertSource, Password) -> {ok, [Entry]} |
-%% {error, Reason}
+-spec encrypt_public(PlainText :: binary(), rsa_public_key()) ->
+ CipherText :: binary().
+-spec encrypt_public(PlainText :: binary(), rsa_public_key(),
+ public_crypt_options()) -> CipherText :: binary().
%%
-%% CertSource = File | CertData
-%% CertData = binary()
-%% File = path()
-%% Entry = {entry_type(), der_bin(), ChipherInfo}
-%% ChipherInfo = opague() | no_encryption
-%% der_bin() = binary()
-%% entry_type() = cert | cert_req | rsa_private_key | dsa_private_key
-%% dh_params
-%%
-%% Description: decode PEM binary data or a PEM file and return
-%% entries as asn1 der encoded entities. Currently supported entry
-%% types are certificates, certificate requests, rsa private keys and
-%% dsa private keys. In the case of a key entry ChipherInfo will be
-%% private keys and Diffie Hellam parameters .In the case of a key
-%% entry ChipherInfo will be used by decode_private_key/2 if the key
-%% is protected by a password.
+%% Description: Public key encryption using the public key.
%%--------------------------------------------------------------------
-pem_to_der(CertSource) ->
- pem_to_der(CertSource, no_passwd).
+encrypt_public(PlainText, Key) ->
+ encrypt_public(PlainText, Key, []).
-pem_to_der(File, Password) when is_list(File) ->
- pubkey_pem:read_file(File, Password);
-pem_to_der(PemBin, Password) when is_binary(PemBin) ->
- pubkey_pem:decode(PemBin, Password).
+encrypt_public(PlainText, #'RSAPublicKey'{modulus=N,publicExponent=E},
+ Options) when is_binary(PlainText), is_list(Options) ->
+ encrypt_public(PlainText, N,E, Options);
-der_to_pem(File, TypeDerList) ->
- pubkey_pem:write_file(File, TypeDerList).
+encrypt_public(PlainText, #'RSAPrivateKey'{modulus=N,publicExponent=E},
+ Options) when is_binary(PlainText), is_list(Options) ->
+ encrypt_public(PlainText, N,E, Options).
%%--------------------------------------------------------------------
-%% Function: pkix_decode_cert(BerCert, Type) -> {ok, Cert} | {error, Reason}
-%%
-%% BerCert = binary()
-%% Type = plain | otp
-%% Cert = certificate()
+-spec encrypt_private(PlainText :: binary(), rsa_private_key()) ->
+ CipherText :: binary().
+-spec encrypt_private(PlainText :: binary(), rsa_private_key(),
+ public_crypt_options()) -> CipherText :: binary().
%%
-%% Description: Decodes an asn1 ber encoded pkix certificate.
-%% otp - Uses OTP-PKIX.asn1 to decode known extensions and
-%% enhance the signature field in #'Certificate'{} and '#TBSCertificate'{}.
+%% Description: Public key encryption using the private key.
%%--------------------------------------------------------------------
-pkix_decode_cert(BinCert, Type) ->
- pubkey_cert_records:decode_cert(BinCert, Type).
+encrypt_private(PlainText, Key) ->
+ encrypt_private(PlainText, Key, []).
+
+encrypt_private(PlainText, #'RSAPrivateKey'{modulus = N,
+ publicExponent = E,
+ privateExponent = D},
+ Options) when is_binary(PlainText), is_list(Options) ->
+ Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding),
+ crypto:rsa_private_encrypt(PlainText, [crypto:mpint(E),
+ crypto:mpint(N),
+ crypto:mpint(D)], Padding).
%%--------------------------------------------------------------------
-%% Function: pkix_encode_cert(Cert) -> {ok, binary()} | {error, Reason}
-%%
-%% Cert = #'Certificate'{}
+-spec sign(PlainTextOrDigest :: binary(), rsa_digest_type() | dss_digest_type(),
+ rsa_private_key() |
+ dsa_private_key()) -> Signature :: binary().
%%
-%% Description: Encodes a certificate record using asn1.
+%% Description: Create digital signature.
%%--------------------------------------------------------------------
-pkix_encode_cert(Cert) ->
- pubkey_cert_records:encode_cert(Cert).
+sign(PlainText, DigestType, #'RSAPrivateKey'{modulus = N, publicExponent = E,
+ privateExponent = D})
+ when is_binary(PlainText),
+ DigestType == md5;
+ DigestType == sha ->
+ crypto:rsa_sign(DigestType, sized_binary(PlainText), [crypto:mpint(E),
+ crypto:mpint(N),
+ crypto:mpint(D)]);
+
+sign(Digest, none, #'DSAPrivateKey'{p = P, q = Q, g = G, x = X})
+ when is_binary(Digest)->
+ crypto:dss_sign(none, Digest,
+ [crypto:mpint(P), crypto:mpint(Q),
+ crypto:mpint(G), crypto:mpint(X)]);
+
+sign(PlainText, sha, #'DSAPrivateKey'{p = P, q = Q, g = G, x = X})
+ when is_binary(PlainText) ->
+ crypto:dss_sign(sized_binary(PlainText),
+ [crypto:mpint(P), crypto:mpint(Q),
+ crypto:mpint(G), crypto:mpint(X)]).
+
+%%--------------------------------------------------------------------
+-spec verify(PlainTextOrDigest :: binary(), rsa_digest_type() | dss_digest_type(),
+ Signature :: binary(), rsa_public_key()
+ | dsa_public_key()) -> boolean().
+%%
+%% Description: Verifies a digital signature.
+%%--------------------------------------------------------------------
+verify(PlainText, DigestType, Signature,
+ #'RSAPublicKey'{modulus = Mod, publicExponent = Exp})
+ when is_binary (PlainText), DigestType == sha; DigestType == md5 ->
+ crypto:rsa_verify(DigestType,
+ sized_binary(PlainText),
+ sized_binary(Signature),
+ [crypto:mpint(Exp), crypto:mpint(Mod)]);
+
+verify(Digest, none, Signature, {Key, #'Dss-Parms'{p = P, q = Q, g = G}})
+ when is_integer(Key), is_binary(Digest), is_binary(Signature) ->
+ crypto:dss_verify(none,
+ Digest,
+ sized_binary(Signature),
+ [crypto:mpint(P), crypto:mpint(Q),
+ crypto:mpint(G), crypto:mpint(Key)]);
+
+verify(PlainText, sha, Signature, {Key, #'Dss-Parms'{p = P, q = Q, g = G}})
+ when is_integer(Key), is_binary(PlainText), is_binary(Signature) ->
+ crypto:dss_verify(sized_binary(PlainText),
+ sized_binary(Signature),
+ [crypto:mpint(P), crypto:mpint(Q),
+ crypto:mpint(G), crypto:mpint(Key)]).
%%--------------------------------------------------------------------
-%% Function: pkix_transform(CertPart, Op) -> TransformedCertPart
-%%
-%% CertPart = pkix part data
-%% Op = encode | decode
+-spec pkix_sign(#'OTPTBSCertificate'{},
+ rsa_private_key() | dsa_private_key()) -> der_encoded().
%%
-%% Description: Transform parts of a pkix certificate between 'plain' format
-%% and the internal 'otp' format, see pkix_decode_cert/2.
-%% Decode transforms from 'plain' to 'otp' and encode from 'otp' to 'plain'
-%% format.
+%% Description: Sign a pkix x.509 certificate. Returns the corresponding
+%% der encoded 'Certificate'{}
%%--------------------------------------------------------------------
-pkix_transform(CertPart, Op) ->
- pubkey_cert_records:transform(CertPart, Op).
+pkix_sign(#'OTPTBSCertificate'{signature =
+ #'SignatureAlgorithm'{algorithm = Alg}
+ = SigAlg} = TBSCert, Key) ->
+
+ Msg = pkix_encode('OTPTBSCertificate', TBSCert, otp),
+ DigestType = pubkey_cert:digest_type(Alg),
+ Signature = sign(Msg, DigestType, Key),
+ Cert = #'OTPCertificate'{tbsCertificate= TBSCert,
+ signatureAlgorithm = SigAlg,
+ signature = {0, Signature}
+ },
+ pkix_encode('OTPCertificate', Cert, otp).
%%--------------------------------------------------------------------
-%% Function: pkix_path_validation(TrustedCert, CertChain, Options) ->
-%% {ok, {{algorithm(), public_key(), public_key_params()} policy_tree()}} |
-%% {error, Reason}
+-spec pkix_verify(der_encoded(), rsa_public_key()|
+ dsa_public_key()) -> boolean().
%%
-%% Description: Performs a bacis path validation according to RFC 3280.
+%% Description: Verify pkix x.509 certificate signature.
%%--------------------------------------------------------------------
-pkix_path_validation(TrustedCert, CertChain, Options)
- when is_binary(TrustedCert) ->
- {ok, OtpCert} = pkix_decode_cert(TrustedCert, otp),
- pkix_path_validation(OtpCert, CertChain, Options);
+pkix_verify(DerCert, {Key, #'Dss-Parms'{}} = DSAKey)
+ when is_binary(DerCert), is_integer(Key) ->
+ {DigestType, PlainText, Signature} = pubkey_cert:verify_data(DerCert),
+ verify(PlainText, DigestType, Signature, DSAKey);
-pkix_path_validation(#'OTPCertificate'{} = TrustedCert, CertChain, Options)
- when is_list(CertChain), is_list(Options) ->
- MaxPathDefault = length(CertChain),
- ValidationState = pubkey_cert:init_validation_state(TrustedCert,
- MaxPathDefault,
- Options),
- Fun = proplists:get_value(validate_extensions_fun, Options,
- fun(Extensions, State, _, AccError) ->
- {Extensions, State, AccError}
- end),
- Verify = proplists:get_value(verify, Options, true),
- path_validation(CertChain, ValidationState, Fun, Verify).
-%%--------------------------------------------------------------------
-%% Function: pkix_is_fixed_dh_cert(Cert) -> true | false
+pkix_verify(DerCert, #'RSAPublicKey'{} = RSAKey)
+ when is_binary(DerCert) ->
+ {DigestType, PlainText, Signature} = pubkey_cert:verify_data(DerCert),
+ verify(PlainText, DigestType, Signature, RSAKey).
+
+%%--------------------------------------------------------------------
+-spec pkix_is_issuer(Cert :: der_encoded()| #'OTPCertificate'{},
+ IssuerCert :: der_encoded()|
+ #'OTPCertificate'{}) -> boolean().
%%
-%% Description: Checks if a Certificate is a fixed Diffie-Hellman Cert
+%% Description: Checks if <IssuerCert> issued <Cert>.
%%--------------------------------------------------------------------
-pkix_is_fixed_dh_cert(#'OTPCertificate'{} = OTPCert) ->
- pubkey_cert:is_fixed_dh_cert(OTPCert);
-pkix_is_fixed_dh_cert(Cert) when is_binary(Cert) ->
- {ok, OtpCert} = pkix_decode_cert(Cert, otp),
- pkix_is_fixed_dh_cert(OtpCert).
+pkix_is_issuer(Cert, IssuerCert) when is_binary(Cert) ->
+ OtpCert = pkix_decode_cert(Cert, otp),
+ pkix_is_issuer(OtpCert, IssuerCert);
+pkix_is_issuer(Cert, IssuerCert) when is_binary(IssuerCert) ->
+ OtpIssuerCert = pkix_decode_cert(IssuerCert, otp),
+ pkix_is_issuer(Cert, OtpIssuerCert);
+pkix_is_issuer(#'OTPCertificate'{tbsCertificate = TBSCert},
+ #'OTPCertificate'{tbsCertificate = Candidate}) ->
+ pubkey_cert:is_issuer(TBSCert#'OTPTBSCertificate'.issuer,
+ Candidate#'OTPTBSCertificate'.subject).
%%--------------------------------------------------------------------
-%% Function: pkix_is_self_signed(Cert) -> true | false
+-spec pkix_is_self_signed(der_encoded()| #'OTPCertificate'{}) -> boolean().
%%
%% Description: Checks if a Certificate is self signed.
%%--------------------------------------------------------------------
pkix_is_self_signed(#'OTPCertificate'{} = OTPCert) ->
pubkey_cert:is_self_signed(OTPCert);
pkix_is_self_signed(Cert) when is_binary(Cert) ->
- {ok, OtpCert} = pkix_decode_cert(Cert, otp),
+ OtpCert = pkix_decode_cert(Cert, otp),
pkix_is_self_signed(OtpCert).
-
+
%%--------------------------------------------------------------------
-%% Function: pkix_issuer_id(Cert) -> {ok, {SerialNr, Issuer}} | {error, Reason}
-%%
-%% Cert = asn1_der_encoded() | 'OTPCertificate'{}
+-spec pkix_is_fixed_dh_cert(der_encoded()| #'OTPCertificate'{}) -> boolean().
%%
+%% Description: Checks if a Certificate is a fixed Diffie-Hellman Cert.
+%%--------------------------------------------------------------------
+pkix_is_fixed_dh_cert(#'OTPCertificate'{} = OTPCert) ->
+ pubkey_cert:is_fixed_dh_cert(OTPCert);
+pkix_is_fixed_dh_cert(Cert) when is_binary(Cert) ->
+ OtpCert = pkix_decode_cert(Cert, otp),
+ pkix_is_fixed_dh_cert(OtpCert).
+
+%%--------------------------------------------------------------------
+-spec pkix_issuer_id(der_encoded()| #'OTPCertificate'{},
+ IssuedBy :: self | other) ->
+ {ok, {SerialNr :: integer(),
+ Issuer :: {rdnSequence,
+ [#'AttributeTypeAndValue'{}]}}}
+ | {error, Reason :: term()}.
+%
%% Description: Returns the issuer id.
%%--------------------------------------------------------------------
pkix_issuer_id(#'OTPCertificate'{} = OtpCert, self) ->
@@ -265,153 +421,112 @@ pkix_issuer_id(#'OTPCertificate'{} = OtpCert, other) ->
pubkey_cert:issuer_id(OtpCert, other);
pkix_issuer_id(Cert, Signed) when is_binary(Cert) ->
- {ok, OtpCert} = pkix_decode_cert(Cert, otp),
+ OtpCert = pkix_decode_cert(Cert, otp),
pkix_issuer_id(OtpCert, Signed).
%%--------------------------------------------------------------------
-%% Function: pkix_is_issuer(Cert, IssuerCert) -> true | false
+-spec pkix_normalize_name({rdnSequence,
+ [#'AttributeTypeAndValue'{}]}) ->
+ {rdnSequence,
+ [#'AttributeTypeAndValue'{}]}.
%%
-%% Cert = asn1_der_encoded() | 'OTPCertificate'{}
-%% IssuerCert = asn1_der_encoded() | 'OTPCertificate'{}
-%%
-%% Description: Checks if <IssuerCert> issued <Cert>.
+%% Description: Normalizes a issuer name so that it can be easily
+%% compared to another issuer name.
%%--------------------------------------------------------------------
-pkix_is_issuer(Cert, IssuerCert) when is_binary(Cert) ->
- {ok, OtpCert} = pkix_decode_cert(Cert, otp),
- pkix_is_issuer(OtpCert, IssuerCert);
+pkix_normalize_name(Issuer) ->
+ pubkey_cert:normalize_general_name(Issuer).
-pkix_is_issuer(Cert, IssuerCert) when is_binary(IssuerCert) ->
- {ok, OtpIssuerCert} = pkix_decode_cert(IssuerCert, otp),
- pkix_is_issuer(Cert, OtpIssuerCert);
+%%--------------------------------------------------------------------
+-spec pkix_path_validation(der_encoded()| #'OTPCertificate'{} | atom(),
+ CertChain :: [der_encoded()] ,
+ Options :: list()) ->
+ {ok, {PublicKeyInfo :: term(),
+ PolicyTree :: term()}} |
+ {error, {bad_cert, Reason :: term()}}.
+%% Description: Performs a basic path validation according to RFC 5280.
+%%--------------------------------------------------------------------
+pkix_path_validation(PathErr, [Cert | Chain], Options0) when is_atom(PathErr)->
+ {VerifyFun, Userstat0} =
+ proplists:get_value(verify_fun, Options0, ?DEFAULT_VERIFYFUN),
+ Otpcert = pkix_decode_cert(Cert, otp),
+ Reason = {bad_cert, PathErr},
+ try VerifyFun(Otpcert, Reason, Userstat0) of
+ {valid, Userstate} ->
+ Options = proplists:delete(verify_fun, Options0),
+ pkix_path_validation(Otpcert, Chain, [{verify_fun,
+ {VerifyFun, Userstate}}| Options]);
+ {fail, _} ->
+ {error, Reason}
+ catch
+ _:_ ->
+ {error, Reason}
+ end;
+pkix_path_validation(TrustedCert, CertChain, Options) when
+ is_binary(TrustedCert) -> OtpCert = pkix_decode_cert(TrustedCert,
+ otp), pkix_path_validation(OtpCert, CertChain, Options);
-pkix_is_issuer(#'OTPCertificate'{tbsCertificate = TBSCert},
- #'OTPCertificate'{tbsCertificate = Candidate}) ->
- pubkey_cert:is_issuer(TBSCert#'OTPTBSCertificate'.issuer,
- Candidate#'OTPTBSCertificate'.subject).
-
-%%--------------------------------------------------------------------
-%% Function: pkix_normalize_general_name(Issuer) ->
-%%
-%% Issuer = general_name() - see PKIX
-%%
-%% Description: Normalizes a general name so that it can be easily
-%% compared to another genral name.
-%%--------------------------------------------------------------------
-pkix_normalize_general_name(Issuer) ->
- pubkey_cert:normalize_general_name(Issuer).
+pkix_path_validation(#'OTPCertificate'{} = TrustedCert, CertChain, Options)
+ when is_list(CertChain), is_list(Options) ->
+ MaxPathDefault = length(CertChain),
+ ValidationState = pubkey_cert:init_validation_state(TrustedCert,
+ MaxPathDefault,
+ Options),
+ path_validation(CertChain, ValidationState).
%%--------------------------------------------------------------------
-%% Function:sign(Msg, Key) -> {ok, Signature}
-%% sign(Msg, Key, KeyParams) -> {ok, Signature}
-%%
-%% Msg = binary() | #'TBSCertificate'{}
-%% Key = private_key()
-%% KeyParams = key_params()
-%% Signature = binary()
-%%
-%% Description: Signs plaintext Msg or #TBSCertificate{}, in the later
-%% case a der encoded "#Certificate{}" will be returned.
+%%% Internal functions
%%--------------------------------------------------------------------
-sign(Msg, #'RSAPrivateKey'{} = Key) when is_binary(Msg) ->
- pubkey_crypto:sign(Msg, Key);
-sign(Msg, #'DSAPrivateKey'{} = Key) when is_binary(Msg) ->
- pubkey_crypto:sign(Msg, Key);
-
-sign(#'OTPTBSCertificate'{signature = #'SignatureAlgorithm'{algorithm = Alg}
- = SigAlg} = TBSCert, Key) ->
- Msg = pubkey_cert_records:encode_tbs_cert(TBSCert),
- DigestType = pubkey_cert:digest_type(Alg),
- Signature = pubkey_crypto:sign(DigestType, Msg, Key),
- Cert = #'OTPCertificate'{tbsCertificate= TBSCert,
- signatureAlgorithm = SigAlg,
- signature = {0, Signature}
- },
- pkix_encode_cert(Cert).
+encrypt_public(PlainText, N, E, Options)->
+ Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding),
+ crypto:rsa_public_encrypt(PlainText, [crypto:mpint(E),crypto:mpint(N)],
+ Padding).
-sign(DigestType, Msg, Key) ->
- pubkey_crypto:sign(DigestType, Msg, Key).
+decrypt_public(CipherText, N,E, Options) ->
+ Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding),
+ crypto:rsa_public_decrypt(CipherText,[crypto:mpint(E), crypto:mpint(N)],
+ Padding).
-%%--------------------------------------------------------------------
-%% Function: verify_signature(PlainText, DigestType, Signature, Key) ->
-%% verify_signature(PlainText, DigestType,
-%% Signature, Key, KeyParams) ->
-%% verify_signature(DerCert, Key, KeyParams) ->
-%%
-%% PlainText = binary()
-%% DigestType = md5 | sha
-%% DerCert = asn1_der_encoded()
-%% Signature = binary()
-%% Key = public_key()
-%% KeyParams = key_params()
-%% Verified = boolean()
-%%
-%% Description: Verifies the signature <Signature>.
-%%--------------------------------------------------------------------
-verify_signature(PlainText, DigestType, Signature, #'RSAPublicKey'{} = Key)
- when is_binary(PlainText), is_binary(Signature), DigestType == sha;
- DigestType == md5 ->
- pubkey_crypto:verify(DigestType, PlainText, Signature, Key, undefined).
-
-verify_signature(PlainText, DigestType, Signature, #'RSAPublicKey'{} = Key,
- KeyParams)
- when is_binary(PlainText), is_binary(Signature), DigestType == sha;
- DigestType == md5 ->
- pubkey_crypto:verify(DigestType, PlainText, Signature, Key, KeyParams);
-verify_signature(PlainText, sha, Signature, Key, #'Dss-Parms'{} = KeyParams)
- when is_binary(PlainText), is_binary(Signature), is_integer(Key) ->
- pubkey_crypto:verify(sha, PlainText, Signature, Key, KeyParams);
-verify_signature(Hash, none, Signature, Key, KeyParams) ->
- pubkey_crypto:verify(none, Hash, Signature, Key, KeyParams).
-
-verify_signature(DerCert, Key, #'Dss-Parms'{} = KeyParams)
- when is_binary(DerCert), is_integer(Key) ->
- pubkey_cert:verify_signature(DerCert, Key, KeyParams);
-verify_signature(DerCert, #'RSAPublicKey'{} = Key, KeyParams)
- when is_binary(DerCert) ->
- pubkey_cert:verify_signature(DerCert, Key, KeyParams).
-%%--------------------------------------------------------------------
-%%% Internal functions
-%%--------------------------------------------------------------------
path_validation([], #path_validation_state{working_public_key_algorithm
= Algorithm,
working_public_key =
PublicKey,
working_public_key_parameters
= PublicKeyParams,
- valid_policy_tree = Tree,
- acc_errors = AccErrors
- }, _, _) ->
- {ok, {{Algorithm, PublicKey, PublicKeyParams}, Tree, AccErrors}};
+ valid_policy_tree = Tree
+ }) ->
+ {ok, {{Algorithm, PublicKey, PublicKeyParams}, Tree}};
path_validation([DerCert | Rest], ValidationState = #path_validation_state{
- max_path_length = Len},
- Fun, Verify) when Len >= 0 ->
- try validate(DerCert,
- ValidationState#path_validation_state{last_cert=Rest=:=[]},
- Fun, Verify) of
+ max_path_length = Len}) when Len >= 0 ->
+ try validate(DerCert,
+ ValidationState#path_validation_state{last_cert=Rest=:=[]}) of
#path_validation_state{} = NewValidationState ->
- path_validation(Rest, NewValidationState, Fun, Verify)
+ path_validation(Rest, NewValidationState)
catch
throw:Reason ->
{error, Reason}
end;
-path_validation(_, _, _, true) ->
- {error, {bad_cert, max_path_length_reached}};
-
-path_validation(_, #path_validation_state{working_public_key_algorithm
- = Algorithm,
- working_public_key =
- PublicKey,
- working_public_key_parameters
- = PublicKeyParams,
- valid_policy_tree = Tree,
- acc_errors = AccErrors
- }, _, false) ->
- {ok, {{Algorithm, PublicKey, PublicKeyParams}, Tree,
- [{bad_cert, max_path_length_reached}|AccErrors]}}.
+path_validation([DerCert | _] = Path,
+ #path_validation_state{user_state = UserState0,
+ verify_fun = VerifyFun} =
+ ValidationState) ->
+ Reason = {bad_cert, max_path_length_reached},
+ OtpCert = pkix_decode_cert(DerCert, otp),
+ try VerifyFun(OtpCert, Reason, UserState0) of
+ {valid, UserState} ->
+ path_validation(Path,
+ ValidationState#path_validation_state{
+ max_path_length = 0,
+ user_state = UserState});
+ {fail, _} ->
+ {error, Reason}
+ catch
+ _:_ ->
+ {error, Reason}
+ end.
validate(DerCert, #path_validation_state{working_issuer_name = Issuer,
working_public_key = Key,
@@ -421,38 +536,60 @@ validate(DerCert, #path_validation_state{working_issuer_name = Issuer,
excluded_subtrees = Exclude,
last_cert = Last,
user_state = UserState0,
- acc_errors = AccErr0} =
- ValidationState0, ValidateExtensionFun, Verify) ->
- {ok, OtpCert} = pkix_decode_cert(DerCert, otp),
- %% All validate functions will throw {bad_cert, Reason} if they
- %% fail and Verify = true if Verify = false errors
- %% will be accumulated in the validationstate
- AccErr1 = pubkey_cert:validate_time(OtpCert, AccErr0, Verify),
-
- AccErr2 = pubkey_cert:validate_issuer(OtpCert, Issuer, AccErr1, Verify),
-
- AccErr3 = pubkey_cert:validate_names(OtpCert, Permit, Exclude, Last,
- AccErr2, Verify),
- AccErr4 =
- pubkey_cert:validate_revoked_status(OtpCert, Verify, AccErr3),
+ verify_fun = VerifyFun} =
+ ValidationState0) ->
+
+ OtpCert = pkix_decode_cert(DerCert, otp),
+
+ UserState1 = pubkey_cert:validate_time(OtpCert, UserState0, VerifyFun),
+
+ UserState2 = pubkey_cert:validate_issuer(OtpCert, Issuer, UserState1, VerifyFun),
+
+ UserState3 = pubkey_cert:validate_names(OtpCert, Permit, Exclude, Last,
+ UserState2,VerifyFun),
+
+ UserState4 = pubkey_cert:validate_revoked_status(OtpCert, UserState3, VerifyFun),
- {ValidationState1, UnknownExtensions0, AccErr5} =
- pubkey_cert:validate_extensions(OtpCert, ValidationState0, Verify,
- AccErr4),
- %% We want the key_usage extension to be checked before we validate
+ {ValidationState1, UserState5} =
+ pubkey_cert:validate_extensions(OtpCert, ValidationState0, UserState4,
+ VerifyFun),
+
+ %% We want the key_usage extension to be checked before we validate
%% the signature.
- AccErr6 =
- pubkey_cert:validate_signature(OtpCert, DerCert, Key, KeyParams,
- AccErr5, Verify),
-
- {UnknownExtensions, UserState, AccErr7} =
- ValidateExtensionFun(UnknownExtensions0, UserState0, Verify, AccErr6),
-
- %% Check that all critical extensions have been handled
- AccErr =
- pubkey_cert:validate_unknown_extensions(UnknownExtensions, AccErr7,
- Verify),
+ UserState6 = pubkey_cert:validate_signature(OtpCert, DerCert,
+ Key, KeyParams, UserState5, VerifyFun),
+ UserState = case Last of
+ false ->
+ pubkey_cert:verify_fun(OtpCert, valid, UserState6, VerifyFun);
+ true ->
+ pubkey_cert:verify_fun(OtpCert, valid_peer,
+ UserState6, VerifyFun)
+ end,
+
ValidationState =
- ValidationState1#path_validation_state{user_state = UserState,
- acc_errors = AccErr},
+ ValidationState1#path_validation_state{user_state = UserState},
+
pubkey_cert:prepare_for_next_cert(OtpCert, ValidationState).
+
+sized_binary(Binary) when is_binary(Binary) ->
+ Size = size(Binary),
+ <<?UINT32(Size), Binary/binary>>;
+sized_binary(List) ->
+ sized_binary(list_to_binary(List)).
+
+%%--------------------------------------------------------------------
+%%% Deprecated functions
+%%--------------------------------------------------------------------
+pem_to_der(CertSource) ->
+ {ok, Bin} = file:read_file(CertSource),
+ {ok, pubkey_pem:decode(Bin)}.
+
+decode_private_key(KeyInfo) ->
+ decode_private_key(KeyInfo, no_passwd).
+
+decode_private_key(KeyInfo = {'RSAPrivateKey', _, _}, Password) ->
+ DerEncoded = pubkey_pem:decode_key(KeyInfo, Password),
+ 'OTP-PUB-KEY':decode('RSAPrivateKey', DerEncoded);
+decode_private_key(KeyInfo = {'DSAPrivateKey', _, _}, Password) ->
+ DerEncoded = pubkey_pem:decode_key(KeyInfo, Password),
+ 'OTP-PUB-KEY':decode('DSAPrivateKey', DerEncoded).
diff --git a/lib/public_key/test/Makefile b/lib/public_key/test/Makefile
index 5544339ff2..e20b903942 100644
--- a/lib/public_key/test/Makefile
+++ b/lib/public_key/test/Makefile
@@ -28,7 +28,7 @@ INCLUDES= -I. -I ../include
# ----------------------------------------------------
MODULES= \
- pkey_test \
+ erl_make_certs \
public_key_SUITE \
pkits_SUITE
diff --git a/lib/public_key/test/pkey_test.erl b/lib/public_key/test/erl_make_certs.erl
index 4cf20f0174..8b01ca3ad4 100644
--- a/lib/public_key/test/pkey_test.erl
+++ b/lib/public_key/test/erl_make_certs.erl
@@ -19,7 +19,7 @@
%% Create test certificates
--module(pkey_test).
+-module(erl_make_certs).
-include_lib("public_key/include/public_key.hrl").
-export([make_cert/1, gen_rsa/1, verify_signature/3, write_pem/3]).
@@ -34,7 +34,7 @@
%% version 3
%% subject [] list of the following content
%% {name, Name}
-%% {email, Email}
+%% {email, Email}
%% {city, City}
%% {state, State}
%% {org, Org}
@@ -56,7 +56,7 @@
make_cert(Opts) ->
SubjectPrivateKey = get_key(Opts),
{TBSCert, IssuerKey} = make_tbs(SubjectPrivateKey, Opts),
- Cert = public_key:sign(TBSCert, IssuerKey),
+ Cert = public_key:pkix_sign(TBSCert, IssuerKey),
true = verify_signature(Cert, IssuerKey, undef), %% verify that the keys where ok
{Cert, encode_key(SubjectPrivateKey)}.
@@ -66,8 +66,9 @@ make_cert(Opts) ->
%% @end
%%--------------------------------------------------------------------
write_pem(Dir, FileName, {Cert, Key = {_,_,not_encrypted}}) when is_binary(Cert) ->
- ok = public_key:der_to_pem(filename:join(Dir, FileName ++ ".pem"), [{cert, Cert, not_encrypted}]),
- ok = public_key:der_to_pem(filename:join(Dir, FileName ++ "_key.pem"), [Key]).
+ ok = der_to_pem(filename:join(Dir, FileName ++ ".pem"),
+ [{'Certificate', Cert, not_encrypted}]),
+ ok = der_to_pem(filename:join(Dir, FileName ++ "_key.pem"), [Key]).
%%--------------------------------------------------------------------
%% @doc Creates a rsa key (OBS: for testing only)
@@ -94,18 +95,14 @@ gen_dsa(LSize,NSize) when is_integer(LSize), is_integer(NSize) ->
%% @spec (::binary(), ::tuple()) -> ::boolean()
%% @end
%%--------------------------------------------------------------------
-verify_signature(DerEncodedCert, DerKey, KeyParams) ->
+verify_signature(DerEncodedCert, DerKey, _KeyParams) ->
Key = decode_key(DerKey),
case Key of
#'RSAPrivateKey'{modulus=Mod, publicExponent=Exp} ->
- public_key:verify_signature(DerEncodedCert,
- #'RSAPublicKey'{modulus=Mod, publicExponent=Exp},
- 'NULL');
+ public_key:pkix_verify(DerEncodedCert,
+ #'RSAPublicKey'{modulus=Mod, publicExponent=Exp});
#'DSAPrivateKey'{p=P, q=Q, g=G, y=Y} ->
- public_key:verify_signature(DerEncodedCert, Y, #'Dss-Parms'{p=P, q=Q, g=G});
-
- _ ->
- public_key:verify_signature(DerEncodedCert, Key, KeyParams)
+ public_key:pkix_verify(DerEncodedCert, {Y, #'Dss-Parms'{p=P, q=Q, g=G}})
end.
%%%%%%%%%%%%%%%%%%%%%%%%% Implementation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -132,59 +129,63 @@ decode_key(#'RSAPrivateKey'{} = Key,_) ->
Key;
decode_key(#'DSAPrivateKey'{} = Key,_) ->
Key;
-decode_key(Der = {_,_,_}, Pw) ->
- {ok, Key} = public_key:decode_private_key(Der, Pw),
- Key;
-decode_key(FileOrDer, Pw) ->
- {ok, [KeyInfo]} = public_key:pem_to_der(FileOrDer),
+decode_key(PemEntry = {_,_,_}, Pw) ->
+ public_key:pem_entry_decode(PemEntry, Pw);
+decode_key(PemBin, Pw) ->
+ [KeyInfo] = public_key:pem_decode(PemBin),
decode_key(KeyInfo, Pw).
encode_key(Key = #'RSAPrivateKey'{}) ->
{ok, Der} = 'OTP-PUB-KEY':encode('RSAPrivateKey', Key),
- {rsa_private_key, list_to_binary(Der), not_encrypted};
+ {'RSAPrivateKey', list_to_binary(Der), not_encrypted};
encode_key(Key = #'DSAPrivateKey'{}) ->
{ok, Der} = 'OTP-PUB-KEY':encode('DSAPrivateKey', Key),
- {dsa_private_key, list_to_binary(Der), not_encrypted}.
+ {'DSAPrivateKey', list_to_binary(Der), not_encrypted}.
make_tbs(SubjectKey, Opts) ->
Version = list_to_atom("v"++integer_to_list(proplists:get_value(version, Opts, 3))),
- {Issuer, IssuerKey} = issuer(Opts, SubjectKey),
+
+ IssuerProp = proplists:get_value(issuer, Opts, true),
+ {Issuer, IssuerKey} = issuer(IssuerProp, Opts, SubjectKey),
{Algo, Parameters} = sign_algorithm(IssuerKey, Opts),
SignAlgo = #'SignatureAlgorithm'{algorithm = Algo,
parameters = Parameters},
-
+ Subject = case IssuerProp of
+ true -> %% Is a Root Ca
+ Issuer;
+ _ ->
+ subject(proplists:get_value(subject, Opts),false)
+ end,
+
{#'OTPTBSCertificate'{serialNumber = trunc(random:uniform()*100000000)*10000 + 1,
signature = SignAlgo,
issuer = Issuer,
validity = validity(Opts),
- subject = subject(proplists:get_value(subject, Opts),false),
+ subject = Subject,
subjectPublicKeyInfo = publickey(SubjectKey),
version = Version,
extensions = extensions(Opts)
}, IssuerKey}.
-issuer(Opts, SubjectKey) ->
- IssuerProp = proplists:get_value(issuer, Opts, true),
- case IssuerProp of
- true -> %% Self signed
- {subject(proplists:get_value(subject, Opts), true), SubjectKey};
- {Issuer, IssuerKey} when is_binary(Issuer) ->
- {issuer_der(Issuer), decode_key(IssuerKey)};
- {File, IssuerKey} when is_list(File) ->
- {ok, [{cert, Cert, _}|_]} = public_key:pem_to_der(File),
- {issuer_der(Cert), decode_key(IssuerKey)}
- end.
+issuer(true, Opts, SubjectKey) ->
+ %% Self signed
+ {subject(proplists:get_value(subject, Opts), true), SubjectKey};
+issuer({Issuer, IssuerKey}, _Opts, _SubjectKey) when is_binary(Issuer) ->
+ {issuer_der(Issuer), decode_key(IssuerKey)};
+issuer({File, IssuerKey}, _Opts, _SubjectKey) when is_list(File) ->
+ {ok, [{cert, Cert, _}|_]} = public_key:pem_to_der(File),
+ {issuer_der(Cert), decode_key(IssuerKey)}.
issuer_der(Issuer) ->
- {ok, Decoded} = public_key:pkix_decode_cert(Issuer, otp),
+ Decoded = public_key:pkix_decode_cert(Issuer, otp),
#'OTPCertificate'{tbsCertificate=Tbs} = Decoded,
#'OTPTBSCertificate'{subject=Subject} = Tbs,
Subject.
-subject(undefined, IsCA) ->
- User = if IsCA -> "CA"; true -> os:getenv("USER") end,
+subject(undefined, IsRootCA) ->
+ User = if IsRootCA -> "RootCA"; true -> os:getenv("USER") end,
Opts = [{email, User ++ "@erlang.org"},
{name, User},
{city, "Stockholm"},
@@ -267,7 +268,7 @@ publickey(#'RSAPrivateKey'{modulus=N, publicExponent=E}) ->
subjectPublicKey = Public};
publickey(#'DSAPrivateKey'{p=P, q=Q, g=G, y=Y}) ->
Algo = #'PublicKeyAlgorithm'{algorithm= ?'id-dsa',
- parameters=#'Dss-Parms'{p=P, q=Q, g=G}},
+ parameters={params, #'Dss-Parms'{p=P, q=Q, g=G}}},
#'OTPSubjectPublicKeyInfo'{algorithm = Algo, subjectPublicKey = Y}.
validity(Opts) ->
@@ -289,7 +290,7 @@ sign_algorithm(#'RSAPrivateKey'{}, Opts) ->
end,
{Type, 'NULL'};
sign_algorithm(#'DSAPrivateKey'{p=P, q=Q, g=G}, _Opts) ->
- {?'id-dsa-with-sha1', #'Dss-Parms'{p=P, q=Q, g=G}}.
+ {?'id-dsa-with-sha1', {params,#'Dss-Parms'{p=P, q=Q, g=G}}}.
make_key(rsa, _Opts) ->
%% (OBS: for testing only)
@@ -410,3 +411,11 @@ extended_gcd(A, B) ->
{X, Y} = extended_gcd(B, N),
{Y, X-Y*(A div B)}
end.
+
+pem_to_der(File) ->
+ {ok, PemBin} = file:read_file(File),
+ public_key:pem_decode(PemBin).
+
+der_to_pem(File, Entries) ->
+ PemBin = public_key:pem_encode(Entries),
+ file:write_file(File, PemBin).
diff --git a/lib/public_key/test/pkits_SUITE.erl b/lib/public_key/test/pkits_SUITE.erl
index 5d58b39e26..1d75e1aed2 100644
--- a/lib/public_key/test/pkits_SUITE.erl
+++ b/lib/public_key/test/pkits_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -187,9 +187,9 @@ run([],_) -> ok.
read_certs(Test) ->
File = test_file(Test),
%% io:format("Read ~p ",[File]),
- {ok, Ders} = public_key:pem_to_der(File),
+ Ders = erl_make_certs:pem_to_der(File),
%% io:format("Ders ~p ~n",[length(Ders)]),
- [Cert || {cert,Cert,not_encrypted} <- Ders].
+ [Cert || {'Certificate', Cert, not_encrypted} <- Ders].
test_file(Test) ->
file(?CONV, lists:append(string:tokens(Test, " -")) ++ ".pem").
diff --git a/lib/public_key/test/public_key_SUITE.erl b/lib/public_key/test/public_key_SUITE.erl
index dc1015969a..81e01f3a02 100644
--- a/lib/public_key/test/public_key_SUITE.erl
+++ b/lib/public_key/test/public_key_SUITE.erl
@@ -101,13 +101,12 @@ all(doc) ->
all(suite) ->
[app,
- dh,
- pem_to_der,
- decode_private_key,
+ pk_decode_encode,
encrypt_decrypt,
sign_verify,
pkix,
- pkix_path_validation
+ pkix_path_validation,
+ deprecated
].
%% Test cases starts here.
@@ -120,85 +119,100 @@ app(suite) ->
app(Config) when is_list(Config) ->
ok = test_server:app_test(public_key).
-dh(doc) ->
- "Test diffie-hellman functions file is ok";
-dh(suite) ->
+pk_decode_encode(doc) ->
+ ["Tests pem_decode/1, pem_encode/1, "
+ "der_decode/2, der_encode/2, "
+ "pem_entry_decode/1, pem_entry_decode/2,"
+ "pem_entry_encode/2, pem_entry_encode/3."];
+
+pk_decode_encode(suite) ->
[];
-dh(Config) when is_list(Config) ->
+pk_decode_encode(Config) when is_list(Config) ->
Datadir = ?config(data_dir, Config),
- {ok,[DerDHparams = {dh_params, _, _}]} =
- public_key:pem_to_der(filename:join(Datadir, "dh.pem")),
- {ok, DHps = #'DHParameter'{prime=P,base=G}} = public_key:decode_dhparams(DerDHparams),
- DHKeys = {Private,_Public} = public_key:gen_key(DHps),
- test_server:format("DHparams = ~p~nDH Keys~p~n", [DHps, DHKeys]),
- {_Private,_Public2} = pubkey_crypto:gen_key(diffie_hellman, [crypto:erlint(Private), P, G]),
- ok.
+
+ [{'DSAPrivateKey', DerDSAKey, not_encrypted} = Entry0 ] =
+ erl_make_certs:pem_to_der(filename:join(Datadir, "dsa.pem")),
+
+ DSAKey = public_key:der_decode('DSAPrivateKey', DerDSAKey),
+
+ DSAKey = public_key:pem_entry_decode(Entry0),
+
+ [{'RSAPrivateKey', DerRSAKey, not_encrypted} = Entry1 ] =
+ erl_make_certs:pem_to_der(filename:join(Datadir, "client_key.pem")),
+
+ RSAKey0 = public_key:der_decode('RSAPrivateKey', DerRSAKey),
+
+ RSAKey0 = public_key:pem_entry_decode(Entry1),
+
+ [{'RSAPrivateKey', _, {_,_}} = Entry2] =
+ erl_make_certs:pem_to_der(filename:join(Datadir, "rsa.pem")),
+ true = check_entry_type(public_key:pem_entry_decode(Entry2, "abcd1234"),
+ 'RSAPrivateKey'),
-pem_to_der(doc) ->
- ["Check that supported PEM files are decoded into the expected entry type"];
-pem_to_der(suite) ->
- [];
-pem_to_der(Config) when is_list(Config) ->
- Datadir = ?config(data_dir, Config),
- {ok,DSAKey =[{dsa_private_key, _, not_encrypted}]} =
- public_key:pem_to_der(filename:join(Datadir, "dsa.pem")),
- {ok,[{rsa_private_key, _, _}]} =
- public_key:pem_to_der(filename:join(Datadir, "client_key.pem")),
- {ok, [{rsa_private_key, _, _}]} =
- public_key:pem_to_der(filename:join(Datadir, "rsa.pem")),
- {ok,[{rsa_private_key, _, _}]} =
- public_key:pem_to_der(filename:join(Datadir, "rsa.pem"), "abcd1234"),
- {ok, Bin0} = file:read_file(filename:join(Datadir, "rsa.pem")),
- {ok, [{rsa_private_key, _, _}]} = public_key:pem_to_der(Bin0, "abcd1234"),
-
- {ok,[{dh_params, _, _}]} =
- public_key:pem_to_der(filename:join(Datadir, "dh.pem")),
- {ok,[{cert, _, not_encrypted}]} =
- public_key:pem_to_der(filename:join(Datadir, "client_cert.pem")),
- {ok,[{cert_req, _, _}]} =
- public_key:pem_to_der(filename:join(Datadir, "req.pem")),
- {ok, Certs = [{cert, _, _}, {cert, _, _}]} =
- public_key:pem_to_der(filename:join(Datadir, "cacerts.pem")),
-
- {ok, Bin1} = file:read_file(filename:join(Datadir, "cacerts.pem")),
- {ok, [{cert, _, _}, {cert, _, _}]} = public_key:pem_to_der(Bin1),
-
- ok = public_key:der_to_pem(filename:join(Datadir, "wcacerts.pem"), Certs),
- ok = public_key:der_to_pem(filename:join(Datadir, "wdsa.pem"), DSAKey),
+ Salt0 = crypto:rand_bytes(8),
+ Entry3 = public_key:pem_entry_encode('RSAPrivateKey', RSAKey0,
+ {{"DES-EDE3-CBC", Salt0}, "1234abcd"}),
+
+ RSAKey0 = public_key:pem_entry_decode(Entry3,"1234abcd"),
- {ok, Certs} = public_key:pem_to_der(filename:join(Datadir, "wcacerts.pem")),
- {ok, DSAKey} = public_key:pem_to_der(filename:join(Datadir, "wdsa.pem")),
+ Des3KeyFile = filename:join(Datadir, "des3_client_key.pem"),
- ok.
-%%--------------------------------------------------------------------
-decode_private_key(doc) ->
- ["Check that private keys are decode to the expected key type."];
-decode_private_key(suite) ->
- [];
-decode_private_key(Config) when is_list(Config) ->
- Datadir = ?config(data_dir, Config),
- {ok,[DsaKey = {dsa_private_key, _DsaKey, _}]} =
- public_key:pem_to_der(filename:join(Datadir, "dsa.pem")),
- {ok,[RsaKey = {rsa_private_key, _RsaKey,_}]} =
- public_key:pem_to_der(filename:join(Datadir, "client_key.pem")),
- {ok,[ProtectedRsaKey1 = {rsa_private_key, _ProtectedRsaKey1,_}]} =
- public_key:pem_to_der(filename:join(Datadir, "rsa.pem"), "abcd1234"),
- {ok,[ProtectedRsaKey2 = {rsa_private_key, _ProtectedRsaKey2,_}]} =
- public_key:pem_to_der(filename:join(Datadir, "rsa.pem")),
+ erl_make_certs:der_to_pem(Des3KeyFile, [Entry3]),
- {ok, #'DSAPrivateKey'{}} = public_key:decode_private_key(DsaKey),
- {ok, #'RSAPrivateKey'{}} = public_key:decode_private_key(RsaKey),
- {ok, #'RSAPrivateKey'{}} = public_key:decode_private_key(ProtectedRsaKey1),
- {ok, #'RSAPrivateKey'{}} = public_key:decode_private_key(ProtectedRsaKey2, "abcd1234"),
+ [{'RSAPrivateKey', _, {"DES-EDE3-CBC", Salt0}}] = erl_make_certs:pem_to_der(Des3KeyFile),
+
+ Salt1 = crypto:rand_bytes(8),
+ Entry4 = public_key:pem_entry_encode('RSAPrivateKey', RSAKey0,
+ {{"DES-CBC", Salt1}, "4567efgh"}),
+
+
+ DesKeyFile = filename:join(Datadir, "des_client_key.pem"),
+
+ erl_make_certs:der_to_pem(DesKeyFile, [Entry4]),
+
+ [{'RSAPrivateKey', _, {"DES-CBC", Salt1}} =Entry5] = erl_make_certs:pem_to_der(DesKeyFile),
+
+
+ true = check_entry_type(public_key:pem_entry_decode(Entry5, "4567efgh"),
+ 'RSAPrivateKey'),
+
+ [{'DHParameter', DerDH, not_encrypted} = Entry6] =
+ erl_make_certs:pem_to_der(filename:join(Datadir, "dh.pem")),
+
+ erl_make_certs:der_to_pem(filename:join(Datadir, "new_dh.pem"), [Entry6]),
+
+ DHParameter = public_key:der_decode('DHParameter', DerDH),
+ DHParameter = public_key:pem_entry_decode(Entry6),
+
+ Entry6 = public_key:pem_entry_encode('DHParameter', DHParameter),
+
+ [{'Certificate', DerCert, not_encrypted} = Entry7] =
+ erl_make_certs:pem_to_der(filename:join(Datadir, "client_cert.pem")),
+
+ Cert = public_key:der_decode('Certificate', DerCert),
+ Cert = public_key:pem_entry_decode(Entry7),
+
+ CertEntries = [{'Certificate', _, not_encrypted} = CertEntry0,
+ {'Certificate', _, not_encrypted} = CertEntry1] =
+ erl_make_certs:pem_to_der(filename:join(Datadir, "cacerts.pem")),
+
+ ok = erl_make_certs:der_to_pem(filename:join(Datadir, "wcacerts.pem"), CertEntries),
+ ok = erl_make_certs:der_to_pem(filename:join(Datadir, "wdsa.pem"), [Entry0]),
+
+ NewCertEntries = erl_make_certs:pem_to_der(filename:join(Datadir, "wcacerts.pem")),
+ true = lists:member(CertEntry0, NewCertEntries),
+ true = lists:member(CertEntry1, NewCertEntries),
+ [Entry0] = erl_make_certs:pem_to_der(filename:join(Datadir, "wdsa.pem")),
ok.
+
%%--------------------------------------------------------------------
encrypt_decrypt(doc) ->
[""];
encrypt_decrypt(suite) ->
[];
encrypt_decrypt(Config) when is_list(Config) ->
- {PrivateKey, _DerKey} = pkey_test:gen_rsa(64),
+ {PrivateKey, _DerKey} = erl_make_certs:gen_rsa(64),
#'RSAPrivateKey'{modulus=Mod, publicExponent=Exp} = PrivateKey,
PublicKey = #'RSAPublicKey'{modulus=Mod, publicExponent=Exp},
Msg = list_to_binary(lists:duplicate(5, "Foo bar 100")),
@@ -219,69 +233,81 @@ sign_verify(suite) ->
[];
sign_verify(Config) when is_list(Config) ->
%% Make cert signs and validates the signature using RSA and DSA
- Ca = {_, CaKey} = pkey_test:make_cert([]),
- {ok, PrivateRSA = #'RSAPrivateKey'{modulus=Mod, publicExponent=Exp}} =
- public_key:decode_private_key(CaKey),
+ Ca = {_, CaKey} = erl_make_certs:make_cert([]),
+ PrivateRSA = #'RSAPrivateKey'{modulus=Mod, publicExponent=Exp} =
+ public_key:pem_entry_decode(CaKey),
- CertInfo = {Cert1,CertKey1} = pkey_test:make_cert([{key, dsa}, {issuer, Ca}]),
+ CertInfo = {Cert1,CertKey1} = erl_make_certs:make_cert([{key, dsa}, {issuer, Ca}]),
PublicRSA = #'RSAPublicKey'{modulus=Mod, publicExponent=Exp},
- true = public_key:verify_signature(Cert1, PublicRSA, undefined),
+ true = public_key:pkix_verify(Cert1, PublicRSA),
- {Cert2,_CertKey} = pkey_test:make_cert([{issuer, CertInfo}]),
+ {Cert2,_CertKey} = erl_make_certs:make_cert([{issuer, CertInfo}]),
- {ok, #'DSAPrivateKey'{p=P, q=Q, g=G, y=Y, x=_X}} =
- public_key:decode_private_key(CertKey1),
- true = public_key:verify_signature(Cert2, Y, #'Dss-Parms'{p=P, q=Q, g=G}),
+ #'DSAPrivateKey'{p=P, q=Q, g=G, y=Y, x=_X} =
+ public_key:pem_entry_decode(CertKey1),
+ true = public_key:pkix_verify(Cert2, {Y, #'Dss-Parms'{p=P, q=Q, g=G}}),
%% RSA sign
Msg0 = lists:duplicate(5, "Foo bar 100"),
Msg = list_to_binary(Msg0),
- RSASign = public_key:sign(sha, Msg0, PrivateRSA),
- RSASign = public_key:sign(Msg, PrivateRSA),
- true = public_key:verify_signature(Msg, sha, RSASign, PublicRSA),
- false = public_key:verify_signature(<<1:8, Msg/binary>>, sha, RSASign, PublicRSA),
- false = public_key:verify_signature(Msg, sha, <<1:8, RSASign/binary>>, PublicRSA),
- RSASign = public_key:sign(sha, Msg, PrivateRSA),
-
- RSASign1 = public_key:sign(md5, Msg, PrivateRSA),
- true = public_key:verify_signature(Msg, md5, RSASign1, PublicRSA),
+
+ RSASign = public_key:sign(Msg0, sha, PrivateRSA),
+ RSASign = public_key:sign(Msg, sha, PrivateRSA),
+ true = public_key:verify(Msg, sha, RSASign, PublicRSA),
+ false = public_key:verify(<<1:8, Msg/binary>>, sha, RSASign, PublicRSA),
+ false = public_key:verify(Msg, sha, <<1:8, RSASign/binary>>, PublicRSA),
+
+ RSASign1 = public_key:sign(Msg, md5, PrivateRSA),
+ true = public_key:verify(Msg, md5, RSASign1, PublicRSA),
%% DSA sign
Datadir = ?config(data_dir, Config),
- {ok,[DsaKey = {dsa_private_key, _, _}]} =
- public_key:pem_to_der(filename:join(Datadir, "dsa.pem")),
- {ok, DSAPrivateKey} = public_key:decode_private_key(DsaKey),
+ [DsaKey = {'DSAPrivateKey', _, _}] =
+ erl_make_certs:pem_to_der(filename:join(Datadir, "dsa.pem")),
+ DSAPrivateKey = public_key:pem_entry_decode(DsaKey),
#'DSAPrivateKey'{p=P1, q=Q1, g=G1, y=Y1, x=_X1} = DSAPrivateKey,
- DSASign = public_key:sign(Msg, DSAPrivateKey),
+ DSASign = public_key:sign(Msg, sha, DSAPrivateKey),
DSAPublicKey = Y1,
DSAParams = #'Dss-Parms'{p=P1, q=Q1, g=G1},
- true = public_key:verify_signature(Msg, sha, DSASign, DSAPublicKey, DSAParams),
- false = public_key:verify_signature(<<1:8, Msg/binary>>, sha, DSASign, DSAPublicKey, DSAParams),
- false = public_key:verify_signature(Msg, sha, <<1:8, DSASign/binary>>, DSAPublicKey, DSAParams),
+ true = public_key:verify(Msg, sha, DSASign, {DSAPublicKey, DSAParams}),
+ false = public_key:verify(<<1:8, Msg/binary>>, sha, DSASign,
+ {DSAPublicKey, DSAParams}),
+ false = public_key:verify(Msg, sha, <<1:8, DSASign/binary>>,
+ {DSAPublicKey, DSAParams}),
+
+ Digest = crypto:sha(Msg),
+ DigestSign = public_key:sign(Digest, none, DSAPrivateKey),
+ true = public_key:verify(Digest, none, DigestSign, {DSAPublicKey, DSAParams}),
+ <<_:8, RestDigest/binary>> = Digest,
+ false = public_key:verify(<<1:8, RestDigest/binary>>, none, DigestSign,
+ {DSAPublicKey, DSAParams}),
+ false = public_key:verify(Digest, none, <<1:8, DigestSign/binary>>,
+ {DSAPublicKey, DSAParams}),
ok.
-
+%%--------------------------------------------------------------------
pkix(doc) ->
"Misc pkix tests not covered elsewhere";
pkix(suite) ->
[];
pkix(Config) when is_list(Config) ->
Datadir = ?config(data_dir, Config),
- {ok,Certs0} = public_key:pem_to_der(filename:join(Datadir, "cacerts.pem")),
- {ok,Certs1} = public_key:pem_to_der(filename:join(Datadir, "client_cert.pem")),
- TestTransform = fun({cert, CertDer, not_encrypted}) ->
- {ok, PlainCert} = public_key:pkix_decode_cert(CertDer, plain),
- {ok, OtpCert} = public_key:pkix_decode_cert(CertDer, otp),
- CertDer = public_key:pkix_encode_cert(OtpCert),
- CertDer = public_key:pkix_encode_cert(PlainCert),
-
- OTPSubj = (OtpCert#'OTPCertificate'.tbsCertificate)#'OTPTBSCertificate'.subject,
- Subj = public_key:pkix_transform(OTPSubj, encode),
- {ok, DNEncoded} = 'OTP-PUB-KEY':encode('Name', Subj),
- Subj2 = (PlainCert#'Certificate'.tbsCertificate)#'TBSCertificate'.subject,
- {ok, DNEncoded} = 'OTP-PUB-KEY':encode('Name', Subj2),
- OTPSubj = public_key:pkix_transform(Subj2, decode),
+ Certs0 = erl_make_certs:pem_to_der(filename:join(Datadir, "cacerts.pem")),
+ Certs1 = erl_make_certs:pem_to_der(filename:join(Datadir, "client_cert.pem")),
+ TestTransform = fun({'Certificate', CertDer, not_encrypted}) ->
+ PlainCert = public_key:pkix_decode_cert(CertDer, plain),
+ OtpCert = public_key:pkix_decode_cert(CertDer, otp),
+ CertDer =
+ public_key:pkix_encode('OTPCertificate', OtpCert, otp),
+ CertDer =
+ public_key:pkix_encode('Certificate', PlainCert, plain),
+ OTPTBS = OtpCert#'OTPCertificate'.tbsCertificate,
+ OTPSubj = OTPTBS#'OTPTBSCertificate'.subject,
+ DNEncoded = public_key:pkix_encode('Name', OTPSubj, otp),
+ PlainTBS = PlainCert#'Certificate'.tbsCertificate,
+ Subj2 = PlainTBS#'TBSCertificate'.subject,
+ DNEncoded = public_key:pkix_encode('Name', Subj2, plain),
false = public_key:pkix_is_fixed_dh_cert(CertDer)
end,
@@ -290,26 +316,31 @@ pkix(Config) when is_list(Config) ->
true = public_key:pkix_is_self_signed(element(2,hd(Certs0))),
false = public_key:pkix_is_self_signed(element(2,hd(Certs1))),
- CaIds = [element(2, public_key:pkix_issuer_id(Cert, self)) || {cert, Cert, _} <- Certs0],
- {ok, IssuerId = {_, IssuerName}} = public_key:pkix_issuer_id(element(2,hd(Certs1)), other),
+ CaIds = [element(2, public_key:pkix_issuer_id(Cert, self)) ||
+ {'Certificate', Cert, _} <- Certs0],
+ {ok, IssuerId = {_, _IssuerName}} =
+ public_key:pkix_issuer_id(element(2,hd(Certs1)), other),
+
true = lists:member(IssuerId, CaIds),
%% Should be normalized allready
- TestStr = {rdnSequence, [[{'AttributeTypeAndValue', {2,5,4,3},{printableString,"ERLANGCA"}}],
- [{'AttributeTypeAndValue', {2,5,4,3},{printableString," erlang ca "}}]]},
- VerifyStr = {rdnSequence, [[{'AttributeTypeAndValue', {2,5,4,3},{printableString,"erlang ca"}}],
- [{'AttributeTypeAndValue', {2,5,4,3},{printableString,"erlangca"}}]]},
- VerifyStr = public_key:pkix_normalize_general_name(TestStr),
+ TestStr = {rdnSequence,
+ [[{'AttributeTypeAndValue', {2,5,4,3},{printableString,"ERLANGCA"}}],
+ [{'AttributeTypeAndValue', {2,5,4,3},{printableString," erlang ca "}}]]},
+ VerifyStr = {rdnSequence,
+ [[{'AttributeTypeAndValue', {2,5,4,3},{printableString,"erlang ca"}}],
+ [{'AttributeTypeAndValue', {2,5,4,3},{printableString,"erlangca"}}]]},
+ VerifyStr = public_key:pkix_normalize_name(TestStr),
ok.
-
+%%--------------------------------------------------------------------
pkix_path_validation(doc) ->
"Misc pkix tests not covered elsewhere";
pkix_path_validation(suite) ->
[];
pkix_path_validation(Config) when is_list(Config) ->
CaK = {Trusted,_} =
- pkey_test:make_cert([{key, dsa},
+ erl_make_certs:make_cert([{key, dsa},
{subject, [
{name, "Public Key"},
{?'id-at-name', {printableString, "public_key"}},
@@ -320,26 +351,89 @@ pkix_path_validation(Config) when is_list(Config) ->
{org_unit, "testing dep"}
]}
]),
- ok = pkey_test:write_pem("./", "public_key_cacert", CaK),
+ ok = erl_make_certs:write_pem("./", "public_key_cacert", CaK),
- CertK1 = {Cert1, _} = pkey_test:make_cert([{issuer, CaK}]),
- CertK2 = {Cert2,_} = pkey_test:make_cert([{issuer, CertK1}, {digest, md5}, {extensions, false}]),
- ok = pkey_test:write_pem("./", "public_key_cert", CertK2),
+ CertK1 = {Cert1, _} = erl_make_certs:make_cert([{issuer, CaK}]),
+ CertK2 = {Cert2,_} = erl_make_certs:make_cert([{issuer, CertK1},
+ {digest, md5}, {extensions, false}]),
+ ok = erl_make_certs:write_pem("./", "public_key_cert", CertK2),
{ok, _} = public_key:pkix_path_validation(Trusted, [Cert1], []),
- {error, {bad_cert,invalid_issuer}} = public_key:pkix_path_validation(Trusted, [Cert2], []),
- %%{error, {bad_cert,invalid_issuer}} = public_key:pkix_path_validation(Trusted, [Cert2], [{verify,false}]),
+ {error, {bad_cert,invalid_issuer}} =
+ public_key:pkix_path_validation(Trusted, [Cert2], []),
{ok, _} = public_key:pkix_path_validation(Trusted, [Cert1, Cert2], []),
{error, issuer_not_found} = public_key:pkix_issuer_id(Cert2, other),
- CertK3 = {Cert3,_} = pkey_test:make_cert([{issuer, CertK1}, {extensions, [{basic_constraints, false}]}]),
- {Cert4,_} = pkey_test:make_cert([{issuer, CertK3}]),
- {error, E={bad_cert,missing_basic_constraint}} =
+ CertK3 = {Cert3,_} = erl_make_certs:make_cert([{issuer, CertK1},
+ {extensions, [{basic_constraints, false}]}]),
+ {Cert4,_} = erl_make_certs:make_cert([{issuer, CertK3}]),
+ {error, {bad_cert,missing_basic_constraint}} =
public_key:pkix_path_validation(Trusted, [Cert1, Cert3,Cert4], []),
-
- {ok, {_,_,[E]}} = public_key:pkix_path_validation(Trusted, [Cert1, Cert3,Cert4], [{verify,false}]),
- % test_server:format("PV ~p ~n", [Result]),
+ VerifyFunAndState0 = {fun(_,{bad_cert, missing_basic_constraint}, UserState) ->
+ {valid, UserState};
+ (_,{bad_cert, _} = Reason, _) ->
+ {fail, Reason};
+ (_,{extension, _}, UserState) ->
+ {unknown, UserState};
+ (_, valid, UserState) ->
+ {valid, UserState};
+ (_, valid_peer, UserState) ->
+ {valid, UserState}
+ end, []},
+ {ok, _} =
+ public_key:pkix_path_validation(Trusted, [Cert1, Cert3,Cert4],
+ [{verify_fun, VerifyFunAndState0}]),
+
+ {error, {bad_cert, unknown_ca}} =
+ public_key:pkix_path_validation(unknown_ca, [Cert1, Cert3, Cert4], []),
+
+ VerifyFunAndState1 =
+ {fun(_,{bad_cert, unknown_ca}, UserState) ->
+ {valid, UserState};
+ (_,{bad_cert, _} = Reason, _) ->
+ {fail, Reason};
+ (_,{extension, _}, UserState) ->
+ {unknown, UserState};
+ (_, valid, UserState) ->
+ {valid, UserState}
+ end, []},
+
+ {ok, _} =
+ public_key:pkix_path_validation(unknown_ca, [Cert1], [{verify_fun,
+ VerifyFunAndState1}]),
ok.
+
+%%--------------------------------------------------------------------
+deprecated(doc) ->
+ ["Check deprecated functions."];
+deprecated(suite) ->
+ [];
+deprecated(Config) when is_list(Config) ->
+ Datadir = ?config(data_dir, Config),
+ {ok, [DsaKey = {'DSAPrivateKey', _DsaKey, _}]} =
+ public_key:pem_to_der(filename:join(Datadir, "dsa.pem")),
+ {ok, [RsaKey = {'RSAPrivateKey', _RsaKey,_}]} =
+ public_key:pem_to_der(filename:join(Datadir, "client_key.pem")),
+ {ok, [ProtectedRsaKey = {'RSAPrivateKey', _ProtectedRsaKey,_}]} =
+ public_key:pem_to_der(filename:join(Datadir, "rsa.pem")),
+
+ {ok, #'DSAPrivateKey'{}} = public_key:decode_private_key(DsaKey),
+ {ok, #'RSAPrivateKey'{}} = public_key:decode_private_key(RsaKey),
+ {ok, #'RSAPrivateKey'{}} = public_key:decode_private_key(ProtectedRsaKey, "abcd1234"),
+ ok.
+
+%%--------------------------------------------------------------------
+
+check_entry_type(#'DSAPrivateKey'{}, 'DSAPrivateKey') ->
+ true;
+check_entry_type(#'RSAPrivateKey'{}, 'RSAPrivateKey') ->
+ true;
+check_entry_type(#'DHParameter'{}, 'DHParameter') ->
+ true;
+check_entry_type(#'Certificate'{}, 'Certificate') ->
+ true;
+check_entry_type(_,_) ->
+ false.
diff --git a/lib/public_key/vsn.mk b/lib/public_key/vsn.mk
index 4b3071a85b..2810942171 100644
--- a/lib/public_key/vsn.mk
+++ b/lib/public_key/vsn.mk
@@ -1,11 +1 @@
-PUBLIC_KEY_VSN = 0.7
-
-TICKETS = OTP-8626 OTP-8649
-
-#TICKETS_0.6 = OTP-7046 \
-# OTP-8553
-#TICKETS_0.5 = OTP-8372
-#TICKETS_0.4 = OTP-8250
-#TICKETS_0.3 = OTP-8100 OTP-8142
-#TICKETS_0.2 = OTP-7860
-#TICKETS_0.1 = OTP-7637 \ No newline at end of file
+PUBLIC_KEY_VSN = 0.9
diff --git a/lib/reltool/test/Makefile b/lib/reltool/test/Makefile
index 34781ae720..5109058797 100644
--- a/lib/reltool/test/Makefile
+++ b/lib/reltool/test/Makefile
@@ -74,7 +74,8 @@ release_spec: opt
release_tests_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) reltool.spec $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)
- $(INSTALL_PROGRAM) rtt $(INSTALL_PROGS) $(RELSYSDIR)
+ $(INSTALL_SCRIPT) rtt $(INSTALL_PROGS) $(RELSYSDIR)
+ $(INSTALL_DATA) $(INSTALL_PROGS) $(RELSYSDIR)
# chmod -f -R u+w $(RELSYSDIR)
# @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
diff --git a/lib/reltool/vsn.mk b/lib/reltool/vsn.mk
index f23a7e84a2..9e0bce1d01 100644
--- a/lib/reltool/vsn.mk
+++ b/lib/reltool/vsn.mk
@@ -1,28 +1 @@
-# This is an -*-makefile-*- file.
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2009-2010. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-
RELTOOL_VSN = 0.5.4
-
-TICKETS = OTP-8521 OTP-8590
-TICKETS_0_5_3 = OTP-8057
-TICKETS_0_5_2 = OTP-8254
-TICKETS_0_5_1 = OTP-8199
-TICKETS_0_5 = OTP-7949
-TICKETS_0_2_2 = OTP-7999
-TICKETS_2_2_1 = OTP-7840
-TICKETS_0_2 = OTP-7805
diff --git a/lib/runtime_tools/c_src/trace_file_drv.c b/lib/runtime_tools/c_src/trace_file_drv.c
index 482fcc0288..cd54f36af0 100644
--- a/lib/runtime_tools/c_src/trace_file_drv.c
+++ b/lib/runtime_tools/c_src/trace_file_drv.c
@@ -520,7 +520,7 @@ static int do_write(FILETYPE fd, unsigned char *buff, int siz) {
*/
static int my_write(TraceFileData *data, unsigned char *buff, int siz)
{
- int wrote, w;
+ int wrote;
if (data->buff_siz - data->buff_pos >= siz) {
memcpy(data->buff + data->buff_pos, buff, siz);
diff --git a/lib/runtime_tools/doc/src/notes.xml b/lib/runtime_tools/doc/src/notes.xml
index e1f954dda7..92629c18e5 100644
--- a/lib/runtime_tools/doc/src/notes.xml
+++ b/lib/runtime_tools/doc/src/notes.xml
@@ -31,6 +31,27 @@
<p>This document describes the changes made to the Runtime_Tools
application.</p>
+<section><title>Runtime_Tools 1.8.4.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Minor corrections and removal of a temporary workaround.</p>
+ <p>
+ Own Id: OTP-8755 Aux Id: seq-11628, seq-11639 </p>
+ </item>
+ <item>
+ <p>
+ Small fix in inviso_autostart_server.</p>
+ <p>
+ Own Id: OTP-8783 Aux Id: seq11628 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Runtime_Tools 1.8.4</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/runtime_tools/src/inviso_autostart.erl b/lib/runtime_tools/src/inviso_autostart.erl
index 134133ad1f..787292e244 100644
--- a/lib/runtime_tools/src/inviso_autostart.erl
+++ b/lib/runtime_tools/src/inviso_autostart.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -59,17 +59,10 @@ autostart(_AutoModArgs) ->
case try_load_module(FileNames) of
ok ->
autostart_apply(M,F);
+
false -> % No such module available
"inviso_autostart.config"
end;
- {ok,{gettia_asc,asc_file}} -> % Uggly hack to not have to change in GSN-CPS.
- case try_load_module(["/tmp/DPE_COMMONLOG/gettia_asc",
- "/tmp/DPE_COMMONLOG/gettia_overload"]) of
- ok ->
- autostart_apply(gettia_asc,asc_file);
- false -> % No such module available
- false
- end;
{ok,{M,F}} -> % Use M:F(node())
autostart_apply(M,F);
{ok,no_autostart} ->
diff --git a/lib/runtime_tools/src/inviso_autostart_server.erl b/lib/runtime_tools/src/inviso_autostart_server.erl
index 5af96e4e39..1e352822f4 100644
--- a/lib/runtime_tools/src/inviso_autostart_server.erl
+++ b/lib/runtime_tools/src/inviso_autostart_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -84,7 +84,7 @@ init(ArgsFromConfig) ->
case get_tracerdata_opts(ArgsFromConfig) of
{ok,TracerData} -> % Otherwise we can not start a trace!
case inviso_rt:init_tracing(TracerData) of
- {ok,_} -> % Ok, tracing has been initiated.
+ {ok,_Response} -> % Ok, tracing has been initiated.
case get_cmdfiles_opts(ArgsFromConfig) of
{ok,CmdFiles} -> % List of cmd-files.
Bindings=get_initialbindings_opts(ArgsFromConfig),
@@ -164,11 +164,11 @@ interpret_cmd_files([{FileName,LocalBindings}|Rest],GlobalBindings,Translations,
Bindings=join_local_and_global_vars(LocalBindings,GlobalBindings),
interpret_cmd_files_1(FileName,Bindings,Translations,Dbg),
interpret_cmd_files(Rest,GlobalBindings,Translations,Dbg);
-interpret_cmd_files([FileName|Rest],GlobalBindings,Translations,Dbg) ->
- interpret_cmd_files_1(FileName,GlobalBindings,Translations,Dbg),
- interpret_cmd_files(Rest,GlobalBindings,Translations,Dbg);
interpret_cmd_files([],_,_,_) -> % Done, return nothing significant!
- true.
+ true;
+interpret_cmd_files(FileName,GlobalBindings,Translations,Dbg) ->
+ interpret_cmd_files_1(FileName,GlobalBindings,Translations,Dbg).
+% interpret_cmd_files(Rest,GlobalBindings,Translations,Dbg).
%% This is "inline" inviso calls.
interpret_cmd_files_1({inviso,F,Args},Bindings,Translations,Dbg) ->
diff --git a/lib/runtime_tools/test/Makefile b/lib/runtime_tools/test/Makefile
new file mode 100644
index 0000000000..873d395277
--- /dev/null
+++ b/lib/runtime_tools/test/Makefile
@@ -0,0 +1,65 @@
+#
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+MODULES = \
+ runtime_tools_SUITE \
+ inviso_testmodule1_foo \
+ inviso_SUITE \
+ dbg_SUITE \
+ erts_alloc_config_SUITE
+
+ERL_FILES= $(MODULES:%=%.erl)
+
+TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+INSTALL_PROGS= $(TARGET_FILES)
+
+EMAKEFILE=Emakefile
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/runtime_tools_test
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+
+ERL_MAKE_FLAGS +=
+ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include
+
+EBIN = .
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+make_emakefile:
+ $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES)\
+ > $(EMAKEFILE)
+
+tests debug opt: make_emakefile
+ erl $(ERL_MAKE_FLAGS) -make
+
+clean:
+ rm -f $(EMAKEFILE)
+ rm -f $(TARGET_FILES)
+ rm -f core
+
+docs:
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_spec: opt
+
+release_tests_spec: make_emakefile
+ $(INSTALL_DIR) $(RELSYSDIR)
+ $(INSTALL_DATA) runtime_tools.spec $(ERL_FILES) $(RELSYSDIR)
+ $(INSTALL_DATA) $(EMAKEFILE) runtime_tools.cover $(RELSYSDIR)
+ chmod -f -R u+w $(RELSYSDIR)
+ @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+
+release_docs_spec:
diff --git a/lib/runtime_tools/test/dbg_SUITE.erl b/lib/runtime_tools/test/dbg_SUITE.erl
new file mode 100644
index 0000000000..ff96af5e86
--- /dev/null
+++ b/lib/runtime_tools/test/dbg_SUITE.erl
@@ -0,0 +1,901 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(dbg_SUITE).
+
+%% Test functions
+-export([all/1, big/1, tiny/1, simple/1, message/1, distributed/1,
+ ip_port/1, file_port/1, file_port2/1, file_port_schedfix/1,
+ ip_port_busy/1, wrap_port/1, wrap_port_time/1,
+ with_seq_trace/1, dead_suspend/1, local_trace/1,
+ saved_patterns/1]).
+-export([init_per_testcase/2, fin_per_testcase/2]).
+-export([tracee1/1, tracee2/1]).
+-export([dummy/0, exported/1]).
+
+-include("test_server.hrl").
+-define(default_timeout, ?t:minutes(1)).
+
+init_per_testcase(_Case, Config) ->
+ ?line Dog=test_server:timetrap(?default_timeout),
+ [{watchdog, Dog}|Config].
+fin_per_testcase(_Case, Config) ->
+ Dog=?config(watchdog, Config),
+ test_server:timetrap_cancel(Dog),
+ ok.
+
+all(suite) -> [big, tiny, simple, message, distributed,
+ ip_port, file_port, file_port2, file_port_schedfix,
+ ip_port_busy, wrap_port, wrap_port_time,
+ with_seq_trace, dead_suspend, local_trace, saved_patterns].
+
+big(suite) -> [];
+big(doc) -> ["Rudimentary interface test"];
+big(Config) when is_list(Config) ->
+ ?line {ok,OldCurDir} = file:get_cwd(),
+ Datadir=?config(data_dir, Config),
+ Privdir=?config(priv_dir, Config),
+ ?line ok=file:set_cwd(Privdir),
+ try
+ %% make sure dbg is stopped (and returns correctly)
+ ?line ok = dbg:stop(),
+
+ %% compile test module and make sure it is loaded.
+ ?line {ok,Mod} = compile:file(Datadir++"/dbg_test",[trace]),
+ ?line code:purge(dbg_test),
+ ?line {module, Mod}=code:load_file(dbg_test),
+
+ %% run/debug a named test function.
+ ?line Pid = spawn_link(dbg_test, loop, [Config]),
+ ?line true = register(dbg_test_loop, Pid),
+ ?line {ok,_} = dbg:tracer(),
+ ?line {ok,[{matched, _node, 1}]} = dbg:p(dbg_test_loop, [m,p,c]),
+ ?line ok = dbg:c(dbg_test, test, [Config]),
+ ?line ok = dbg:i(),
+ ?line dbg_test_loop ! {dbg_test, stop},
+ unregister(dbg_test_loop),
+ ?line ok = dbg:stop(),
+
+ %% run/debug a Pid.
+ ?line Pid2=spawn_link(dbg_test,loop,[Config]),
+ ?line {ok,_} = dbg:tracer(),
+ ?line {ok,[{matched, _node, 1}]} = dbg:p(Pid2,[s,r,p]),
+ ?line ok = dbg:c(dbg_test, test, [Config]),
+ ?line ok = dbg:i(),
+ ?line Pid2 ! {dbg_test, stop},
+
+ ?line ok=file:set_cwd(OldCurDir)
+ after
+ ?line dbg:stop()
+ end,
+ ok.
+
+
+tiny(suite) -> [];
+tiny(doc) -> ["Rudimentary interface test"];
+tiny(Config) when is_list(Config) ->
+ ?line {ok,OldCurDir} = file:get_cwd(),
+ Datadir=?config(data_dir, Config),
+ Privdir=?config(priv_dir, Config),
+ ?line ok=file:set_cwd(Privdir),
+ try
+ %% compile test module and make sure it is loaded.
+ ?line {ok, Mod} = compile:file(Datadir++"/dbg_test",[trace]),
+ ?line code:purge(dbg_test),
+ ?line {module, Mod}=code:load_file(dbg_test),
+
+ ?line Pid=spawn_link(dbg_test,loop,[Config]),
+ if
+ is_pid(Pid) ->
+ ?line dbg:tracer(),
+ ?line {ok,[{matched, _node, 1}]} = dbg:p(Pid,[s,r,m,p,c]),
+ ?line ok = dbg:c(dbg_test,test,[Config]),
+ ?line ok = dbg:i(),
+ ?line Pid ! {dbg_test, stop};
+ true ->
+ ?line ok=file:set_cwd(OldCurDir),
+ ?t:fail("Could not spawn external test process.~n"),
+ failure
+ end
+ after
+ ?line ok = dbg:stop(),
+ ?line ok = file:set_cwd(OldCurDir)
+ end,
+ ok.
+
+simple(suite) ->
+ [];
+simple(doc) ->
+ ["Simple interface test with own handler"];
+simple(Config) when is_list(Config) ->
+ try
+ ?line start(),
+ ?line dbg:p(self(),call),
+ ?line dbg:tp(dbg,ltp,[]),
+ ?line dbg:ltp(),
+ ?line stop(),
+ ?line S = self(),
+ ?line [{trace,S,call,{dbg,ltp,[]}}] = flush()
+ after
+ ?line dbg:stop()
+ end,
+ ok.
+
+message(suite) ->
+ [];
+message(doc) ->
+ ["Simple interface test with pam code that appends a message"];
+message(Config) when is_list(Config) ->
+ ?line {ok, _} = start(),
+ try
+ ?line {ok, [{matched, _node, 1}]} = dbg:p(self(),call),
+ ?line {ok, X} = dbg:tp(dbg,ltp,[{'_',[],[{message, {self}}]}]),
+ ?line {value, {saved, Saved}} = lists:keysearch(saved, 1, X),
+ ?line {ok, Y} = dbg:tp(dbg,ln,Saved),
+ ?line {value, {saved, Saved}} = lists:keysearch(saved, 1, Y),
+ ?line ok = dbg:ltp(),
+ ?line ok = dbg:ln()
+ after
+ ?line stop()
+ end,
+ ?line S = self(),
+ ?line [{trace,S,call,{dbg,ltp,[]},S},
+ {trace,S,call,{dbg,ln,[]},S}] = flush(),
+ ok.
+
+distributed(suite) ->
+ [];
+distributed(doc) ->
+ ["Simple test of distributed tracing"];
+distributed(Config) when is_list(Config) ->
+ ?line {ok, _} = start(),
+ ?line Node = start_slave(),
+ try
+ ?line RexPid = rpc:call(Node, erlang, whereis, [rex]),
+ ?line RexPidList = pid_to_list(RexPid),
+ ?line {ok, Node} = dbg:n(Node),
+ ?line {ok, X} = dbg:p(all,call),
+ ?line {value, {matched, Node, _}} = lists:keysearch(Node, 2, X),
+ ?line {ok, Y} = dbg:p(RexPidList, s),
+ ?line {value, {matched, Node, 1}} = lists:keysearch(Node, 2, Y),
+ ?line {ok, Z} = dbg:tp(dbg,ltp,[]),
+ ?line {value, {matched, Node, 1}} = lists:keysearch(Node, 2, Z),
+ ?line dbg:cn(Node),
+ ?line dbg:tp(dbg,ln,[]),
+ ?line ok = rpc:call(Node, dbg, ltp, []),
+ ?line ok = rpc:call(Node, dbg, ln, []),
+ ?line ok = dbg:ln(),
+ ?line S = self(),
+ ?line {TraceSend, TraceCall} =
+ lists:partition(fun ({trace,RP,send,_,_}) when RP =:= RexPid -> true;
+ (_) -> false end,
+ flush()),
+ ?line [_|_] = TraceSend,
+ ?line [{trace,Pid,call,{dbg,ltp,[]}},
+ {trace,S,call,{dbg,ln,[]}}] = TraceCall,
+ ?line Node = node(Pid),
+ %%
+ ?line stop()
+ after
+ ?line stop_slave(Node),
+ ?line stop()
+ end,
+ ok.
+
+
+local_trace(suite) ->
+ [];
+local_trace(doc) ->
+ ["Tests tracing of local function calls."];
+local_trace(Config) when is_list(Config) ->
+ ?line {ok, _} = start(),
+ try
+ ?line S = self(),
+ ?line %% Split "<X.Y.Z>" into {X, Y, Z}
+ ?line "<"++L1 = L = pid_to_list(S),
+ ?line NoDot = fun ($.) -> false; (_) -> true end,
+ ?line {LX,"."++L2} = lists:splitwith(NoDot, L1),
+ ?line {LY,"."++L3} = lists:splitwith(NoDot, L2),
+ ?line ">"++L4 = lists:reverse(L3),
+ ?line LZ = lists:reverse(L4),
+ ?line X = 0 = list_to_integer(LX),
+ ?line Y = list_to_integer(LY),
+ ?line Z = list_to_integer(LZ),
+ ?line XYZ = {X, Y, Z},
+ ?line io:format("Self = ~w = ~w~n", [S,XYZ]),
+ ?line {ok, [{matched, _node, 1}]} = dbg:p(S,call),
+ ?line {ok, [{matched, _node, 1}]} = dbg:p(XYZ,call),
+ if Z =:= 0 ->
+ ?line {ok, [{matched, _node, 1}]} = dbg:p(Y,call);
+ true -> ok
+ end,
+ ?line {ok, [{matched, _node, 1}]} = dbg:p(L,call),
+ ?line {ok, _} = dbg:tpl(?MODULE,not_exported,[]),
+ ?line 4 = not_exported(2),
+ ?line [{trace,S,call,{?MODULE,not_exported,[2]}}] = flush(),
+ ?line {ok, _} = dbg:tp(?MODULE,exported,[]),
+ ?line 4 = ?MODULE:exported(2),
+ ?line [{trace,S,call,{?MODULE,exported,[2]}},
+ {trace,S,call,{?MODULE,not_exported,[2]}}] = flush(),
+ ?line {ok, _} = dbg:ctpl(?MODULE),
+ ?line 4 = ?MODULE:exported(2),
+ ?line [{trace,S,call,{?MODULE,exported,[2]}}] = flush(),
+ ?line {ok, _} = dbg:tpl(?MODULE,not_exported,[]),
+ ?line {ok, _} = dbg:ctp(?MODULE),
+ ?line 4 = ?MODULE:exported(2),
+ ?line [] = flush(),
+ ?line {ok, _} = dbg:tpl(?MODULE,not_exported,x),
+ ?line catch ?MODULE:exported(x),
+ ?line [{trace,S,call,{dbg_SUITE,not_exported,[x]}},
+ {trace,S,exception_from,
+ {dbg_SUITE,not_exported,1},
+ {error,badarith}}] = flush()
+ after
+ ?line stop()
+ end,
+ ok.
+
+saved_patterns(suite) ->
+ [];
+saved_patterns(doc) ->
+ ["Tests saving of match_spec's."];
+saved_patterns(Config) when is_list(Config) ->
+ ?line dbg:stop(),
+ ?line {ok,[{saved,1}]} =
+ dbg:tp(dbg,ctp,1,[{'_',[],[{message, blahonga}]}]),
+ ?line {ok,[{saved,2}]} =
+ dbg:tp(dbg,ctp,1,[{['_'],[],[{message, blahonga}]}]),
+ ?line Privdir=?config(priv_dir, Config),
+ ?line file:make_dir(Privdir),
+ ?line File = filename:join([Privdir, "blahonga.ms"]),
+ ?line dbg:wtp(File),
+ ?line dbg:stop(),
+ ?line dbg:ctp('_','_','_'),
+ ?line {ok, _} = start(),
+ try
+ ?line dbg:rtp(File),
+ ?line {ok,[{matched,_node,1},{saved,1}]} = dbg:tp(dbg,ltp,0,1),
+ ?line {ok, [{matched, _node, 1}]} = dbg:p(self(),call),
+ ?line dbg:ltp(),
+ ?line S = self(),
+ ?line [{trace,S,call,{dbg,ltp,[]},blahonga}] = flush()
+ after
+ ?line stop()
+ end,
+ ok.
+
+
+
+not_exported(N) ->
+ N * 2.
+
+exported(N) ->
+ not_exported(N).
+
+ip_port(suite) ->
+ [];
+ip_port(doc) ->
+ ["Test tracing to IP port"];
+ip_port(Config) when is_list(Config) ->
+ ?line stop(),
+ ?line Port = dbg:trace_port(ip, 0),
+ ?line {ok, _} = dbg:tracer(port, Port),
+ try
+ ?line {ok, [{matched, _node, 1}]} = dbg:p(self(),call),
+ ?line {ok, X} = dbg:tp(dbg, ltp,[{'_',[],[{message, {self}}]}]),
+ ?line {value, {saved, _Saved}} = lists:keysearch(saved, 1, X),
+ ?line {ok, Y} = dbg:tp(dbg, ln, [{'_',[],[{message, hej}]}]),
+ ?line {value, {saved, _}} = lists:keysearch(saved, 1, Y),
+ ?line ok = dbg:ltp(),
+ ?line ok = dbg:ln(),
+ ?line {ok, IpPort} = dbg:trace_port_control(get_listen_port),
+ ?line io:format("IpPort = ~p~n", [IpPort]),
+ ?line dbg:trace_client(ip, IpPort, {fun myhandler/2, self()}),
+ ?line S = self(),
+ ?line [{trace,S,call,{dbg,ltp,[]},S},
+ {trace,S,call,{dbg,ln,[]},hej}] = flush()
+ after
+ ?line stop()
+ end,
+ ok.
+
+
+
+ip_port_busy(suite) ->
+ [];
+ip_port_busy(doc) ->
+ ["Test that the dbg server does not hang if the tracer don't start ",
+ "(OTP-3592)"];
+ip_port_busy(Config) when is_list(Config) ->
+ ?line stop(),
+ ?line Tracer = dbg:trace_port(ip, 4745),
+ ?line Port = Tracer(),
+ ?line {error, Reason} = dbg:tracer(port, Tracer),
+ try
+ ?line io:format("Error reason = ~p~n", [Reason]),
+ ?line true = port_close(Port)
+ after
+ ?line dbg:stop()
+ end,
+ ?line ok.
+
+
+
+file_port(suite) ->
+ [];
+file_port(doc) ->
+ ["Test tracing to file port (simple)"];
+file_port(Config) when is_list(Config) ->
+ ?line stop(),
+ ?line {A,B,C} = erlang:now(),
+ ?line FTMP = atom_to_list(?MODULE) ++ integer_to_list(A) ++ "-" ++
+ integer_to_list(B) ++ "-" ++ integer_to_list(C),
+ ?line FName = filename:join([?config(data_dir, Config), FTMP]),
+ ?line Port = dbg:trace_port(file, FName),
+ ?line {ok, _} = dbg:tracer(port, Port),
+ try
+ ?line {ok, [{matched, _node, 1}]} = dbg:p(self(),call),
+ ?line {ok, X} = dbg:tp(dbg, ltp,[{'_',[],[{message, {self}}]}]),
+ ?line {value, {saved, _Saved}} = lists:keysearch(saved, 1, X),
+ ?line {ok, Y} = dbg:tp(dbg, ln, [{'_',[],[{message, hej}]}]),
+ ?line {value, {saved, _}} = lists:keysearch(saved, 1, Y),
+ ?line ok = dbg:ltp(),
+ ?line ok = dbg:ln(),
+ ?line stop(),
+ ?line dbg:trace_client(file, FName, {fun myhandler/2, self()}),
+ ?line S = self(),
+ ?line [{trace,S,call,{dbg,ltp,[]},S},
+ {trace,S,call,{dbg,ln,[]},hej},
+ end_of_trace] = flush()
+ after
+ ?line stop(),
+ ?line file:delete(FName)
+ end,
+ ok.
+
+file_port2(suite) ->
+ [];
+file_port2(doc) ->
+ ["Test tracing to file port with 'follow_file'"];
+file_port2(Config) when is_list(Config) ->
+ case os:type() of
+ vxworks ->
+ {skipped, "VxWorks NFS cache ruins it all."};
+ _ ->
+ ?line stop(),
+ ?line {A,B,C} = erlang:now(),
+ ?line FTMP = atom_to_list(?MODULE) ++ integer_to_list(A) ++
+ "-" ++ integer_to_list(B) ++ "-" ++ integer_to_list(C),
+ ?line FName = filename:join([?config(data_dir, Config), FTMP]),
+ %% Ok, lets try with flush and follow_file, not a chance on VxWorks
+ %% with NFS caching...
+ ?line Port2 = dbg:trace_port(file, FName),
+ ?line {ok, _} = dbg:tracer(port, Port2),
+ try
+ ?line {ok, [{matched, _node, 1}]} = dbg:p(self(),call),
+ ?line {ok, _} = dbg:tp(dbg, ltp,[{'_',[],[{message, {self}}]}]),
+ ?line {ok, _} = dbg:tp(dbg, ln, [{'_',[],[{message, hej}]}]),
+ ?line ok = dbg:ltp(),
+ ?line ok = dbg:flush_trace_port(),
+ ?line dbg:trace_client(follow_file, FName,
+ {fun myhandler/2, self()}),
+ ?line S = self(),
+ ?line [{trace,S,call,{dbg,ltp,[]},S}] = flush(),
+ ?line ok = dbg:ln(),
+ ?line ok = dbg:flush_trace_port(),
+ ?line receive after 1000 -> ok end, %% Polls every second...
+ ?line [{trace,S,call,{dbg,ln,[]},hej}] = flush(),
+ ?line stop(),
+ ?line [] = flush()
+ after
+ ?line stop(),
+ ?line file:delete(FName)
+ end,
+ ok
+ end.
+
+file_port_schedfix(suite) ->
+ [];
+file_port_schedfix(doc) ->
+ ["Test that the scheduling timestamp fix for trace flag 'running' works."];
+file_port_schedfix(Config) when is_list(Config) ->
+ ?line case (catch erlang:system_info(smp_support)) of
+ true ->
+ {skip, "No schedule fix on SMP"};
+ _ ->
+ try
+ file_port_schedfix1(Config)
+ after
+ dbg:stop()
+ end
+ end.
+file_port_schedfix1(Config) when is_list(Config) ->
+ ?line stop(),
+ ?line {A,B,C} = erlang:now(),
+ ?line FTMP = atom_to_list(?MODULE) ++ integer_to_list(A) ++
+ "-" ++ integer_to_list(B) ++ "-" ++ integer_to_list(C),
+ ?line FName = filename:join([?config(data_dir, Config), FTMP]),
+ %%
+ ?line Port = dbg:trace_port(file, {FName, wrap, ".wraplog", 8*1024, 4}),
+ ?line {ok, _} = dbg:tracer(port, Port),
+ ?line {ok,[{matched,_node,0}]} = dbg:p(new,[running,procs,send,timestamp]),
+ %%
+ %% Generate the trace data
+ %%
+ %% This starts 3 processes that sends a message to each other in a ring,
+ %% 4 laps. Prior to sending the message to the next in the ring, each
+ %% process send 8 messages to itself, just to generate some trace data,
+ %% and to lower the possibility that the trace log wraps just after
+ %% a schedule out message (which would not burden any process and hence
+ %% not show up in the result)
+ %%
+ %% The wrap file trace is used because it burns a lot of time when the
+ %% driver swaps files, a lot more than the regular file trace. The test
+ %% case is dimensioned so that the log fills two files and just starts
+ %% on the third (out of four wrap files). This gives two file swaps,
+ %% and there are three processes, so one process will NOT be burdened.
+ %% The criterion for trace success is then that the max process
+ %% execution time must not be more than twice the min process
+ %% execution time. Wallclock. A normal result is about 10 times more
+ %% without schedule in - schedule out compensation (OTP-3938).
+ %%
+ ?line ok = token_volleyball(3, 4, 8),
+ %%
+ ?line {ok,[{matched,_,_}]} = dbg:p(all, [clear]),
+ ?line stop(),
+ % Some debug code to run on all platforms, for finding the fault on genny
+ % Dont touch please /PaN
+ ?line io:format("Trace dump by PaN BEGIN~n"),
+ ?line dbg:trace_client(file,{FName, wrap, ".wraplog"},{fun(end_of_trace,Pid)-> Pid ! done; (Mesg,Pid) -> io:format("~w~n",[Mesg]),Pid end,self()}),
+ receive done -> ok end,
+ ?line io:format("Trace dump by PaN END~n"),
+ %%
+ %% Get the trace result
+ %%
+ ?line Tag = make_ref(),
+ ?line dbg:trace_client(file, {FName, wrap, ".wraplog"},
+ {fun schedstat_handler/2, {self(), Tag, []}}),
+ ?line Result =
+ receive
+ {Tag, D} ->
+ lists:map(
+ fun({Pid, {A1, B1, C1}}) ->
+ {Pid, C1/1000000 + B1 + A1*1000000}
+ end,
+ D)
+ end,
+ ?line ok = io:format("Result=~p", [Result]),
+% erlang:display({?MODULE, ?LINE, Result}),
+ %%
+ %% Analyze the result
+ %%
+ ?line {Min, Max} =
+ lists:foldl(
+ fun({_Pid, M}, {Mi, Ma}) ->
+ {if M < Mi -> M; true -> Mi end,
+ if M > Ma -> M; true -> Ma end}
+ end,
+ {void, 0},
+ Result),
+ % More PaN debug
+ ?line io:format("Min = ~f, Max = ~f~n",[Min,Max]),
+ %%
+ %% Cleanup
+ %%
+ ?line ToBeDeleted = filelib:wildcard(FName++"*"++".wraplog"),
+ ?line lists:map({file, delete}, ToBeDeleted),
+% io:format("ToBeDeleted=~p", [ToBeDeleted]),
+ %%
+ %% Present the result
+ %%
+ P = (Max / Min - 1) * 100,
+ BottomLine = lists:flatten(io_lib:format("~.2f %", [P])),
+ if P > 100 ->
+ Reason = {BottomLine, '>', "100%"},
+ erlang:display({file_port_schedfix, fail, Reason}),
+ test_server:fail(Reason);
+ true ->
+ {comment, BottomLine}
+ end.
+
+wrap_port(suite) ->
+ [];
+wrap_port(doc) ->
+ ["Test tracing to wrapping file port"];
+wrap_port(Config) when is_list(Config) ->
+ ?line Self = self(),
+ ?line stop(),
+ ?line {A,B,C} = erlang:now(),
+ ?line FTMP = atom_to_list(?MODULE) ++ integer_to_list(A) ++ "-" ++
+ integer_to_list(B) ++ "-" ++ integer_to_list(C) ++ "-",
+ ?line FName = filename:join([?config(data_dir, Config), FTMP]),
+ ?line FNameWildcard = FName++"*"++".trace",
+ %% WrapSize=0 and WrapCnt=11 will force the trace to wrap after
+ %% every trace message, and to contain only the last 10 entries
+ %% after trace stop since the last file will be empty waiting
+ %% for its first trace message.
+ ?line WrapSize = 0,
+ ?line WrapCnt = 11,
+ ?line WrapFilesSpec = {FName, wrap, ".trace", WrapSize, WrapCnt},
+ ?line wrap_port_init(WrapFilesSpec),
+ %% The number of iterations, N, is tested to place wrap the log,
+ %% giving a gap in the filename sequence at index 3.
+ %% This should be a difficult case for
+ %% the trace_client file sorting functionality.
+ N = 7,
+ ?line lists:foreach(
+ fun(Cnt) ->
+ ?MODULE:tracee1(Cnt),
+ ?MODULE:tracee2(Cnt)
+ end,
+ lists:seq(1, N)),
+ ?line stop(),
+ try
+ ?line Files1 = filelib:wildcard(FNameWildcard),
+ ?line io:format("~p~n", [Files1]),
+ ?line Tc1 = dbg:trace_client(file, WrapFilesSpec,
+ {fun myhandler/2, {wait_for_go,Self}}),
+ ?line Tref1 = erlang:monitor(process, Tc1),
+ Tc1 ! {go,Self},
+ ?line [{'DOWN',Tref1,_,_,normal},
+ end_of_trace
+ |Result] = lists:reverse(flush()),
+ ?line M = N - (WrapCnt-1) div 2,
+ ?line M = wrap_port_result(Result, Self, N),
+ %%
+ %% Start a new wrap log with the same name to verify that
+ %% all files are cleared at wrap log start. Only produce
+ %% two trace messages to also place the gap at index 3,
+ %% so the trace log will be misinterpreted.
+ %%
+ ?line wrap_port_init(WrapFilesSpec),
+ ?line Files2 = filelib:wildcard(FNameWildcard),
+ ?line io:format("~p~n", [Files2]),
+ ?line -1 = ?MODULE:tracee1(-1),
+ ?line -1 = ?MODULE:tracee2(-1),
+ ?line stop(),
+ ?line Files = filelib:wildcard(FNameWildcard),
+ ?line io:format("~p~n", [Files]),
+ ?line Tc2 = dbg:trace_client(file, WrapFilesSpec,
+ {fun myhandler/2, {wait_for_go,Self}}),
+ ?line Tref2 = erlang:monitor(process, Tc2),
+ Tc2 ! {go,Self},
+ ?line [{trace,Self,call,{?MODULE,tracee1,[-1]},Self},
+ {trace,Self,call,{?MODULE,tracee2,[-1]},hej},
+ end_of_trace,
+ {'DOWN',Tref2,_,_,normal}] = flush(),
+ %%
+ ?line lists:map(fun(F) -> file:delete(F) end, Files)
+ after
+ ?line stop()
+ end,
+ ok.
+
+wrap_port_init(WrapFilesSpec) ->
+ ?line Port = dbg:trace_port(file, WrapFilesSpec),
+ ?line {ok, _} = dbg:tracer(port, Port),
+ ?line {ok, [{matched, _node, 1}]} = dbg:p(self(),call),
+ ?line {ok, X} = dbg:tp(?MODULE, tracee1,[{'_',[],[{message, {self}}]}]),
+ ?line {value, {saved, _Saved}} = lists:keysearch(saved, 1, X),
+ ?line {ok, Y} = dbg:tp(?MODULE, tracee2, [{'_',[],[{message, hej}]}]),
+ ?line {value, {saved, _}} = lists:keysearch(saved, 1, Y),
+ ok.
+
+tracee1(X) ->
+ X.
+
+tracee2(X) ->
+ X.
+
+wrap_port_result([], _S, M) ->
+ M;
+wrap_port_result([{trace, S, call, {?MODULE, tracee2, [M]}, hej},
+ {trace, S, call, {?MODULE, tracee1, [M]}, S} | Tail],
+ S,
+ M) ->
+ wrap_port_result(Tail, S, M-1).
+
+
+wrap_port_time(suite) ->
+ [];
+wrap_port_time(doc) ->
+ ["Test tracing to time limited wrapping file port"];
+wrap_port_time(Config) when is_list(Config) ->
+ ?line stop(),
+ ?line {A,B,C} = erlang:now(),
+ ?line FTMP = atom_to_list(?MODULE) ++ integer_to_list(A) ++ "-" ++
+ integer_to_list(B) ++ "-" ++ integer_to_list(C) ++ "-",
+ ?line FName = filename:join([?config(data_dir, Config), FTMP]),
+ %% WrapTime=2 and WrapCnt=4 will force the trace to wrap after
+ %% every 2 seconds, and to contain between 3*2 and 4*2 seconds
+ %% of trace entries.
+ ?line WrapFilesSpec = {FName, wrap, ".trace", {time, 2000}, 4},
+ ?line Port = dbg:trace_port(file, WrapFilesSpec),
+ ?line {ok, _} = dbg:tracer(port, Port),
+ try
+ ?line {ok, [{matched, _node, 1}]} = dbg:p(self(),call),
+ ?line {ok, X} = dbg:tp(?MODULE, tracee1,[{'_',[],[{message, {self}}]}]),
+ ?line {value, {saved, _Saved1}} = lists:keysearch(saved, 1, X),
+ ?line {ok, Y} = dbg:tp(?MODULE, tracee2, [{'_',[],[{message, hej}]}]),
+ ?line {value, {saved, _Saved2}} = lists:keysearch(saved, 1, Y),
+ %% The delays in the iterations places two trace messages in each
+ %% trace file, but the last which is empty waiting for its first
+ %% trace message. The number of iterations is chosen so that
+ %% one trace file has been wasted, and therefore the first pair
+ %% of trace messages.
+ ?line lists:foreach(
+ fun(Cnt) ->
+ receive after 1000 -> ok end,
+ ?MODULE:tracee1(Cnt),
+ ?MODULE:tracee2(Cnt),
+ receive after 1100 -> ok end
+ end,
+ lists:seq(1, 4)),
+ ?line stop(),
+ ?line Files = filelib:wildcard(FName ++ "*" ++ ".trace"),
+ ?line io:format("~p~n", [Files]),
+ ?line dbg:trace_client(file, WrapFilesSpec, {fun myhandler/2, self()}),
+ ?line S = self(),
+ ?line [{trace, S, call, {?MODULE, tracee1, [2]}, S},
+ {trace, S, call, {?MODULE, tracee2, [2]}, hej},
+ {trace, S, call, {?MODULE, tracee1, [3]}, S},
+ {trace, S, call, {?MODULE, tracee2, [3]}, hej},
+ {trace, S, call, {?MODULE, tracee1, [4]}, S},
+ {trace, S, call, {?MODULE, tracee2, [4]}, hej},
+ end_of_trace] = flush(),
+ ?line lists:map(fun(F) -> file:delete(F) end, Files)
+ after
+ ?line stop()
+ end,
+ ok.
+
+with_seq_trace(suite) ->
+ [];
+with_seq_trace(doc) ->
+ ["Test ordinary tracing combined with seq_trace"];
+with_seq_trace(Config) when is_list(Config) ->
+ try
+ ?line {ok, Server} = start(),
+ ?line {ok, Tracer} = dbg:get_tracer(),
+ ?line {ok, X} = dbg:tp(dbg, get_tracer, [{[],[],
+ [{set_seq_token, send, true}]}]),
+ ?line {value, {saved, _}} = lists:keysearch(saved, 1, X),
+ ?line {ok, [{matched, _node, 1}]} = dbg:p(self(),call),
+ ?line seq_trace:set_system_tracer(Tracer),
+ ?line dbg:get_tracer(),
+ receive
+ after 1 ->
+ ok
+ end,
+ ?line S = self(),
+ ?line ThisNode = node(),
+ ?line [{trace,S,call,{dbg,get_tracer,[]}},
+ {seq_trace,0,{send,_,S,Server,{S,{get_tracer,ThisNode}}}},
+ {seq_trace,0,{send,_,Server,S,{dbg,{ok,Tracer}}}}] =
+ flush()
+ after
+ ?line stop()
+ end,
+ ok.
+
+dead_suspend(suite) ->
+ [];
+dead_suspend(doc) ->
+ ["Test that trace messages concerning a now dead process does "
+ "not crash dbg."];
+
+dead_suspend(Config) when is_list(Config) ->
+ ?line start(),
+ try
+ survived = run_dead_suspend()
+ after
+ ?line stop()
+ end.
+
+run_dead_suspend() ->
+ dbg:p(new, call),
+ dbg:tp(?MODULE, dummy, []),
+ spawn(?MODULE, dummy, []),
+ spawn(?MODULE, dummy, []),
+ spawn(?MODULE, dummy, []),
+ spawn(?MODULE, dummy, []),
+ spawn(?MODULE, dummy, []),
+ receive after 1000 -> ok end,
+ case whereis(dbg) of
+ undefined ->
+ died;
+ _ ->
+ survived
+ end.
+
+dummy() ->
+ ok.
+
+
+%%
+%% Support functions
+%%
+
+start_slave() ->
+ {A, B, C} = now(),
+ Name = "asdkxlkmd" ++ integer_to_list(A+B+C),
+ {ok, Node} = test_server:start_node(Name,slave,[]),
+ ok = wait_node(Node, 15),
+ Node.
+
+stop_slave(Node) ->
+ test_server:stop_node(Node).
+
+wait_node(_,0) ->
+ no;
+wait_node(Node, N) ->
+ case net_adm:ping(Node) of
+ pong ->
+ ok;
+ pang ->
+ receive
+ after 1000 ->
+ ok
+ end,
+ wait_node(Node, N - 1)
+ end.
+
+myhandler(Message, {wait_for_go,Pid}) ->
+ receive
+ {go,Pid} ->
+ myhandler(Message, Pid)
+ end;
+myhandler(Message, Relay) ->
+ Relay ! Message,
+ case Message of
+ end_of_trace ->
+ ok;
+ _ ->
+ Relay
+ end.
+
+flush() ->
+ flush([]).
+flush(Acc) ->
+ receive
+ X ->
+ flush(Acc ++ [X])
+ after 1000 ->
+ Acc
+ end.
+
+start() ->
+ stop(),
+ dbg:tracer(process, {fun myhandler/2, self()}).
+
+stop() ->
+ dbg:stop().
+
+
+
+schedstat_handler(TraceMsg, {Parent, Tag, Data} = State) ->
+ case TraceMsg of
+ {trace_ts, Pid, in, _, Ts} ->
+ NewData =
+ case lists:keysearch(Pid, 1, Data) of
+ {value, {Pid, Acc}} ->
+ [{Pid, Acc, Ts} | lists:keydelete(Pid, 1, Data)];
+ false ->
+ [{Pid, {0, 0, 0}, Ts} | Data];
+ Other ->
+ exit(Parent, {?MODULE, ?LINE, Other}),
+ erlang:display({?MODULE, ?LINE, Other}),
+ Data
+ end,
+ {Parent, Tag, NewData};
+ {trace_ts, Pid, out, _, {A3, B3, C3}} ->
+ NewData =
+ case lists:keysearch(Pid, 1, Data) of
+ {value, {Pid, {A1, B1, C1}, {A2, B2, C2}}} ->
+ [{Pid, {A3-A2+A1, B3-B2+B1, C3-C2+C1}} |
+ lists:keydelete(Pid, 1, Data)];
+ Other ->
+ exit(Parent, {?MODULE, ?LINE, Other}),
+ erlang:display({?MODULE, ?LINE, Other}),
+ Data
+ end,
+ {Parent, Tag, NewData};
+ {trace_ts, Pid, exit, normal, {A3, B3, C3}} ->
+ NewData =
+ case lists:keysearch(Pid, 1, Data) of
+ {value, {Pid, {A1, B1, C1}, {A2, B2, C2}}} ->
+ [{Pid, {A3-A2+A1, B3-B2+B1, C3-C2+C1}} |
+ lists:keydelete(Pid, 1, Data)];
+ {value, {Pid, _Acc}} ->
+ Data;
+ false ->
+ [{Pid, {0, 0, 0}} | Data];
+ Other ->
+ exit(Parent, {?MODULE, ?LINE, Other}),
+ erlang:display({?MODULE, ?LINE, Other}),
+ Data
+ end,
+ {Parent, Tag, NewData};
+ {trace_ts, _Pid, send, _Msg, _OtherPid, _Ts} ->
+ State;
+ end_of_trace ->
+ Parent ! {Tag, Data},
+ State
+ end.
+
+
+
+pass_token(Token, Next, Loops) ->
+ receive
+ {Token, 1} = Msg ->
+ sendloop(Loops),
+ Next ! Msg;
+ {Token, _Cnt} = Msg->
+ sendloop(Loops),
+ Next ! Msg,
+ pass_token(Token, Next, Loops)
+ end.
+
+pass_token(Token, Final, Cnt, Loops) ->
+ receive
+ {Token, start, Next} ->
+ sendloop(Loops),
+ Msg = {Token, Cnt},
+ Next ! Msg,
+ pass_token(Token, Final, Next, Cnt, Loops)
+ end.
+
+pass_token(Token, Final, Next, Cnt, Loops) ->
+ receive
+ {Token, 1} ->
+ sendloop(Loops),
+ Msg = {Token, done},
+ Final ! Msg;
+ {Token, Cnt} ->
+ sendloop(Loops),
+ NextCnt = Cnt-1,
+ Msg = {Token, NextCnt},
+ Next ! Msg,
+ pass_token(Token, Final, Next, NextCnt, Loops)
+ end.
+
+sendloop(Loops) ->
+ sendloop(make_ref(), Loops).
+
+sendloop(_Tag, 0) ->
+ ok;
+sendloop(Tag, Loops) ->
+ self() ! {Tag, Loops},
+ receive {Tag, Loops} -> ok end,
+ sendloop(Tag, Loops-1).
+
+token_volleyball(N, Cnt, Loops)
+ when is_integer(N), N >= 1, is_integer(Cnt), Cnt >= 1,
+ is_integer(Loops), Loops >= 0 ->
+ Self = self(),
+ Token = make_ref(),
+ Last = spawn_link(fun() -> pass_token(Token, Self, Cnt, Loops) end),
+ First = token_volleyball(Token, Last, N-1, Loops),
+ Last ! {Token, start, First},
+ receive {Token, done} -> ok end.
+
+token_volleyball(Token, Next, 1, Loops) ->
+ spawn_link(fun() -> pass_token(Token, Next, Loops) end);
+token_volleyball(Token, Next, N, Loops) ->
+ Pid = spawn_link(fun() -> pass_token(Token, Next, Loops) end),
+ token_volleyball(Token, Pid, N-1, Loops).
diff --git a/lib/runtime_tools/test/dbg_SUITE_data/dbg_test.erl b/lib/runtime_tools/test/dbg_SUITE_data/dbg_test.erl
new file mode 100644
index 0000000000..2edbf6f99a
--- /dev/null
+++ b/lib/runtime_tools/test/dbg_SUITE_data/dbg_test.erl
@@ -0,0 +1,87 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%%----------------------------------------------------------------------
+%%% Purpose : A priority queue.
+%%%----------------------------------------------------------------------
+%%% This module implements a priority queue as defined in
+%%% "Priority Queues and the STL" by Mark Nelson in Dr.Dobb's Journal, Jan 1996
+%%% see http://web2.airmail.net/markn/articles/pq_stl/priority.htm for more
+%%% information. (A heap implementation is planned aswell)
+%%%----------------------------------------------------------------------
+%%% The items of the queue is kept priority sorted, and because of that,
+%%% a push() operation costs more than a pop() operation (wich only
+%%% needs to return the top item of the queue(read: list)).
+%%%----------------------------------------------------------------------
+%%% The priority queue can be deceptively nice to use when creating for
+%%% example a Huffman coding tree.
+%%% See http://web2.airmail.net/markn/articles/pq_stl/priority.htm or
+%%% Dr.Dobb's Journal Jan, 96 for more information on this.
+%%%----------------------------------------------------------------------
+
+%%% Used here strictly as something for dbg_SUITE to run.
+
+-module(dbg_test).
+-export([test/1, loop/1]).
+-export([new/0, push/3, pop/1]).
+
+loop(Config) ->
+ test(Config),
+ receive
+ {dbg_test, stop} ->
+ ok;
+ Other ->
+ loop(Config)
+ end,
+ ok.
+
+test(Config) ->
+ Q1=new(),
+ Q2=push(Q1, "monkey", 3),
+ Q3=push(Q2, "banana", 4),
+ Q4=push(Q3, "jungle", 2),
+ Q5=push(Q4, "world", 5),
+ Q6=push(Q5, "universe",6),
+ Q7=push(Q6, "peanut", 1),
+% io:format("~p~n",[Q7]),
+ {Itm, Q8}=pop(Q7),
+ ok.
+
+%% Returns a new priority queue.
+new() ->
+ [].
+
+%% Pushes a new item with a set priority into the queue.
+push(Queue, Itm, Pri) ->
+ insert(Queue, Itm, Pri, []).
+
+%% Pops the item with the highest priority out of the queue.
+pop([{Itm, Pri}|Queue]) ->
+ {Itm, Queue}.
+
+%% --- -- -
+%% Support functions.
+insert([], Itm, Pri, NewQ) ->
+ lists:flatten([lists:reverse(NewQ)|[{Itm, Pri}]]);
+% Itm>QItm>NewQ>Queue
+insert([{QItm,QPri}|Queue], Itm, Pri, NewQ) when Pri>QPri->
+ A = [{Itm, Pri}|[{QItm, QPri}]],
+ lists:flatten([[A|NewQ]|Queue]);
+insert([QItm|Rest], Itm, Pri, NewQ) ->
+ insert(Rest, Itm, Pri, [QItm|NewQ]).
+%% --- -- -
diff --git a/lib/runtime_tools/test/dbg_SUITE_data/exref_td.erl b/lib/runtime_tools/test/dbg_SUITE_data/exref_td.erl
new file mode 100644
index 0000000000..85faf620aa
--- /dev/null
+++ b/lib/runtime_tools/test/dbg_SUITE_data/exref_td.erl
@@ -0,0 +1,50 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(exref_td).
+
+-export([a/1,b/1,c/1,d/1,e/1,my_analyse/1]).
+
+a("edcba") ->
+ true;
+a(_) ->
+ lists:reverse("abcde").
+
+b(_) ->
+ a(nil).
+
+c(_) ->
+ nonexistentmodule:f().
+
+d(_) ->
+ lists:nonexistentfunction().
+
+e(_) ->
+ [a(x),b(x),c(x)].
+
+localfuncnotcalled() ->
+ true.
+
+localfunccalledbyf(A) ->
+ A.
+
+f() ->
+ lists:filter(fun localfunccalledbyf/1,"aaabba"),
+ F = fun localfuncnotcalled/0.
+
+my_analyse(Graph) -> ok.
diff --git a/lib/runtime_tools/test/erts_alloc_config_SUITE.erl b/lib/runtime_tools/test/erts_alloc_config_SUITE.erl
new file mode 100644
index 0000000000..32483dbe73
--- /dev/null
+++ b/lib/runtime_tools/test/erts_alloc_config_SUITE.erl
@@ -0,0 +1,206 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(erts_alloc_config_SUITE).
+
+%-define(line_trace, 1).
+
+-include("test_server.hrl").
+
+%-compile(export_all).
+-export([all/1, init_per_testcase/2, fin_per_testcase/2]).
+
+%% Testcases
+-export([basic/1]).
+
+%% internal export
+-export([make_basic_config/1]).
+
+-define(DEFAULT_TIMEOUT, ?t:minutes(2)).
+
+all(doc) -> [];
+all(suite) -> [basic].
+
+init_per_testcase(Case, Config) when is_list(Config) ->
+ [{testcase, Case},
+ {watchdog, ?t:timetrap(?DEFAULT_TIMEOUT)},
+ {erl_flags_env, save_env()} | Config].
+
+fin_per_testcase(_Case, Config) when is_list(Config) ->
+ ?t:timetrap_cancel(?config(watchdog, Config)),
+ restore_env(?config(erl_flags_env, Config)),
+ ok.
+
+%%%
+%%% The test cases ------------------------------------------------------------
+%%%
+
+basic(doc) -> [];
+basic(suite) -> [];
+basic(Config) when is_list(Config) ->
+ ?line ErtsAllocConfig = privfile("generated", Config),
+
+ SbctMod = " +MBsbct 1024 +MHsbct 4096",
+
+ %% Make sure we have enabled allocators
+ ZFlgs = case os:getenv("ERL_ZFLAGS") of
+ FlgString when is_list(FlgString) ->
+ FlgString;
+ _ ->
+ ""
+ end ++ " +Mea max +Mea config",
+
+ ?line os:putenv("ERL_ZFLAGS", ZFlgs ++ SbctMod),
+
+ ?line {ok, Node1} = start_node(Config),
+ ?line ok = rpc:call(Node1, ?MODULE, make_basic_config, [ErtsAllocConfig]),
+ ?line stop_node(Node1),
+
+ ?line display_file(ErtsAllocConfig),
+
+ ?line ManualConfig = privfile("manual", Config),
+ ?line {ok, IOD} = file:open(ManualConfig, [write]),
+ ?line io:format(IOD, "~s", ["+MBsbct 2048"]),
+ ?line file:close(IOD),
+ ?line display_file(ManualConfig),
+
+ ?line os:putenv("ERL_ZFLAGS", ZFlgs),
+
+ ?line {ok, Node2} = start_node(Config,
+ "-args_file " ++ ErtsAllocConfig
+ ++ " -args_file " ++ ManualConfig),
+
+ ?line {_, _, _, Cfg} = rpc:call(Node2, erlang, system_info, [allocator]),
+
+ ?line stop_node(Node2),
+
+ ?line {value,{binary_alloc, BCfg}} = lists:keysearch(binary_alloc, 1, Cfg),
+ ?line {value,{sbct, 2097152}} = lists:keysearch(sbct, 1, BCfg),
+ ?line {value,{eheap_alloc, HCfg}} = lists:keysearch(eheap_alloc, 1, Cfg),
+ ?line {value,{sbct, 4194304}} = lists:keysearch(sbct, 1, HCfg),
+
+ ?line ok.
+
+make_basic_config(ErtsAllocConfig) ->
+ %% Save some different scenarios
+ Tester = self(),
+ SSBegun = make_ref(),
+ SSDone = make_ref(),
+ SSFun = fun (F) ->
+ receive
+ SSDone ->
+ ok = erts_alloc_config:save_scenario(),
+ Tester ! SSDone
+ after 500 ->
+ ok = erts_alloc_config:save_scenario(),
+ F(F)
+ end
+ end,
+ SS = spawn_link(fun () ->
+ ok = erts_alloc_config:save_scenario(),
+ Tester ! SSBegun,
+ SSFun(SSFun)
+ end),
+ receive SSBegun -> ok end,
+ Ref = make_ref(),
+ Tab = ets:new(?MODULE, [bag, public]),
+ Ps = lists:map(
+ fun (_) ->
+ spawn_link(
+ fun () ->
+ ets:insert(Tab,
+ {self(),
+ lists:seq(1, 1000)}),
+ receive after 1000 -> ok end,
+ Tester ! {Ref, self()}
+ end)
+ end,
+ lists:seq(1, 10000)),
+ lists:foreach(fun (P) -> receive {Ref, P} -> ok end end, Ps),
+ ets:delete(Tab),
+ SS ! SSDone,
+ receive SSDone -> ok end,
+
+ ok = erts_alloc_config:make_config(ErtsAllocConfig).
+
+
+
+%%
+%% Utils ----------------------------------------------------------------------
+%%
+
+display_file(FileName) ->
+ ?t:format("filename: ~s~n", [FileName]),
+ {ok, Bin} = file:read_file(FileName),
+ io:format("~s", [binary_to_list(Bin)]),
+ ?t:format("eof: ~s~n", [FileName]),
+ ok.
+
+mk_name(Config) when is_list(Config) ->
+ {A, B, C} = now(),
+ list_to_atom(atom_to_list(?MODULE)
+ ++ "-" ++ atom_to_list(?config(testcase, Config))
+ ++ "-" ++ integer_to_list(A)
+ ++ "-" ++ integer_to_list(B)
+ ++ "-" ++ integer_to_list(C)).
+
+start_node(Config) ->
+ start_node(Config, "").
+
+start_node(Config, Args) ->
+ ?line Pa = filename:dirname(code:which(?MODULE)),
+ ?line ?t:start_node(mk_name(Config),
+ slave,
+ [{args, "-pa " ++ Pa ++ " " ++ Args}]).
+
+stop_node(Node) ->
+ ?line true = ?t:stop_node(Node).
+
+privfile(Name, Config) ->
+ filename:join([?config(priv_dir, Config),
+ atom_to_list(?config(testcase, Config)) ++ "." ++ Name]).
+
+save_env() ->
+ {erl_flags,
+ os:getenv("ERL_AFLAGS"),
+ os:getenv("ERL_FLAGS"),
+ os:getenv("ERL_"++erlang:system_info(otp_release)++"_FLAGS"),
+ os:getenv("ERL_ZFLAGS")}.
+
+restore_env(EVar, false) when is_list(EVar) ->
+ restore_env(EVar, "");
+restore_env(EVar, "") when is_list(EVar) ->
+ case os:getenv(EVar) of
+ false -> ok;
+ "" -> ok;
+ " " -> ok;
+ _ -> os:putenv(EVar, " ")
+ end;
+restore_env(EVar, Value) when is_list(EVar), is_list(Value) ->
+ case os:getenv(EVar) of
+ Value -> ok;
+ _ -> os:putenv(EVar, Value)
+ end.
+
+restore_env({erl_flags, AFlgs, Flgs, RFlgs, ZFlgs}) ->
+ restore_env("ERL_AFLAGS", AFlgs),
+ restore_env("ERL_FLAGS", Flgs),
+ restore_env("ERL_"++erlang:system_info(otp_release)++"_FLAGS", RFlgs),
+ restore_env("ERL_ZFLAGS", ZFlgs),
+ ok.
diff --git a/lib/runtime_tools/test/inviso_SUITE.erl b/lib/runtime_tools/test/inviso_SUITE.erl
new file mode 100644
index 0000000000..1c5c887b62
--- /dev/null
+++ b/lib/runtime_tools/test/inviso_SUITE.erl
@@ -0,0 +1,2840 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%% Description:
+%% Test suite for inviso (basic parts, i.e not inviso tools). Note that
+%% inviso basic parts have modules in both the runtime_tools and
+%% inviso applications.
+%%
+%% Authors:
+%% Ann-Marie L�f, [email protected]
+%% Lennart �hman, [email protected]
+%% -----------------------------------------------------------------------------
+
+-module(inviso_SUITE).
+-compile(export_all).
+
+-include("test_server.hrl").
+-include_lib("kernel/include/file.hrl").
+
+-define(l,?line).
+
+all(suite) ->
+ [
+ basic_dist_trace_1,
+ basic_dist_trace_2,
+ basic_dist_trace_3,
+ basic_dist_trace_ti_1,
+ basic_dist_trace_ti_2,
+ basic_dist_trace_ti_3,
+ suspend_dist_trace_ti_1,
+ suspend_dist_trace_ti_2,
+ meta_cleanfunc_dist_1,
+ basic_handlerfun_dist_1,
+ delete_log_dist_1,
+ autostart_dist_1,
+ autostart_dist_2,
+ autostart_dist_3,
+ running_alone_dist_1,
+ running_alone_dist_2,
+ running_alone_dist_3,
+ running_alone_dist_4,
+ running_alone_dist_5,
+ overload_dist_1,
+ overload_dist_2,
+ overload_dist_3,
+ overload_dist_4,
+ overload_dist_5,
+ subscribe_dist_1,
+ lfm_trace_dist_1,
+ lfm_trace_ti_dist_2,
+ handle_logfile_sort_wrapset,
+ fetch_log_dist_trace_1,
+ fetch_log_dist_trace_2,
+ fetch_log_dist_trace_3,
+ fetch_log_dist_error_1,
+ fetch_log_dist_error_2,
+ expand_regexp_dist_1,
+ only_loaded_dist_1
+ ].
+
+
+init_per_suite(Config) ->
+ %% No never know who skrewed up this node before this suite! :-)
+ erlang:trace_pattern({'_','_','_'},[],[local]),
+ erlang:trace_pattern({'_','_','_'},[],[global]),
+ erlang:trace(all,false,[all]),
+
+ ?l ok=application:start(runtime_tools),
+ Config.
+
+end_per_suite(_Config) ->
+ ?l ok=application:stop(runtime_tools).
+
+
+%% For each distributed testcase, we need two other distributed nodes to run the
+%% runtime components on. Since they are freshly started every time there is no
+%% need to clean them up first.
+init_per_testcase(_Case,Config) ->
+ ?l TH=test_server:timetrap(100000),
+ ?l {ok,Node1}=test_server:start_node(inviso1,peer,[]),
+ ?l {ok,Node2}=test_server:start_node(inviso2,peer,[]),
+ ?l SuiteDir=filename:dirname(code:which(?MODULE)),
+
+ %% Otherwise peer nodes will not find this module!
+ ?l true=rpc:call(Node1,code,add_patha,[SuiteDir]),
+ ?l true=rpc:call(Node2,code,add_patha,[SuiteDir]),
+
+ ?l start_side_effect_logger(node()),
+ ?l start_side_effect_logger(Node1),
+ ?l start_side_effect_logger(Node2),
+
+
+ %% SPECIAL FOR MY PRIVATE TEST ENVIROMENT
+% ?l rpc:call(Node1,code,add_patha,["/clearcase/otp/tools/runtime_tools/ebin"]),
+% ?l rpc:call(Node1,code,add_patha,["/clearcase/otp/tools/inviso/ebin"]),
+% ?l rpc:call(Node2,code,add_patha,["/clearcase/otp/tools/runtime_tools/ebin"]),
+% ?l rpc:call(Node2,code,add_patha,["/clearcase/otp/tools/inviso/ebin"]),
+
+% %% SPECIAL FOR MY PRIVATE TEST ENVIROMENT, windows.
+% ?l rpc:call(Node1,code,add_patha,["Z:/DATA/PROJECTS/inviso_project/runtime_tools/ebin"]),
+% ?l rpc:call(Node1,code,add_patha,["Z:/DATA/PROJECTS/inviso_project/inviso/ebin"]),
+% ?l rpc:call(Node2,code,add_patha,["Z:/DATA/PROJECTS/inviso_project/runtime_tools/ebin"]),
+% ?l rpc:call(Node2,code,add_patha,["Z:/DATA/PROJECTS/inviso_project/inviso/ebin"]),
+
+ ?l ok=rpc:call(Node1,application,start,[runtime_tools]),
+ ?l ok=rpc:call(Node2,application,start,[runtime_tools]),
+ ?l timer:sleep(100), % Problem with autostarted runtime.
+ %% The following is a test that the inviso_rt processes which are autostarted
+ %% are now gone.
+
+ ?l ok=poll(rpc,call,[Node1,erlang,whereis,[inviso_rt]],undefined,20),
+ ?l ok=poll(rpc,call,[Node2,erlang,whereis,[inviso_rt]],undefined,20),
+
+% ?l ok=poll(rpc,call,[Node1,supervisor,which_children,[runtime_tools_sup]],[],20),
+% ?l ok=poll(rpc,call,[Node2,supervisor,which_children,[runtime_tools_sup]],[],20),
+ NewConfig1=insert_remotenode_config(inviso1,Node1,Config),
+ NewConfig2=insert_remotenode_config(inviso2,Node2,NewConfig1),
+ insert_timetraphandle_config(TH,NewConfig2).
+%% -----------------------------------------------------------------------------
+
+fin_per_testcase(Case,Config) ->
+ ?l test_server:stop_node(get_remotenode_config(inviso1,Config)),
+ ?l test_server:stop_node(get_remotenode_config(inviso2,Config)),
+
+ case whereis(inviso_c) of
+ undefined -> % Should not exist.
+ true;
+ Pid when is_pid(Pid) -> % But if it exists...
+ exit(Pid,kill), % Remove it!
+ io:format("Had to kill the control component in fin_per_testcase,~p.~n",[Case])
+ end,
+ case whereis(inviso_rt) of
+ undefined -> % Should not exist.
+ true;
+ Pid2 when is_pid(Pid2) -> % But if it exists...
+ exit(Pid2,kill), % Remove it!
+ io:format("Had to kill local runtime component in fin_per_testcase,~p.~n",[Case])
+ end,
+ ?l process_killer([inviso_test_proc,
+ inviso_tab_proc,
+ inviso_collector_proc,
+ global_inviso_test_proc]),
+ ?l test_server:timetrap_cancel(get_timetraphandle_config(Config)),
+
+ NewConfig1=remove_remotenode_config(inviso1,Config),
+ NewConfig2=remove_remotenode_config(inviso2,NewConfig1),
+ remove_timetraphandle_config(NewConfig2).
+%% -----------------------------------------------------------------------------
+
+%% ==============================================================================
+%% Testcases.
+%% ==============================================================================
+
+%% TEST CASE: Basic, distributed, trace only.
+basic_dist_trace_1(suite) -> [];
+basic_dist_trace_1(doc) ->
+ ["Basic case, start of distributed tracing, using only trac."];
+basic_dist_trace_1(Config) when is_list(Config) ->
+ RemoteNodes=get_remotenodes_config(Config),
+ Nodes=[node()|RemoteNodes],
+ PrivDir=filename:join(?config(priv_dir,Config),""),
+ TracerDataList=lists:map(fun(N)->{N,{file,filename:join([PrivDir,
+ "tf1_"++
+ atom_to_list(N)
+ ])}} end,
+ Nodes),
+ start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok}]}),
+ activate_local_tracing(Nodes),
+ deactivate_local_tracing(Nodes),
+ stop_tracing(Nodes),
+ stop(Nodes),
+ ok.
+%% -----------------------------------------------------------------------------
+
+
+%% TEST CASE: Basic, distributed, activate global tracing for functions in modules
+%% pointed out using a regexp. No tracing will be done.
+basic_dist_trace_2(suite) -> [];
+basic_dist_trace_2(doc) ->
+ [""];
+basic_dist_trace_2(Config) when is_list(Config) ->
+ RemoteNodes=get_remotenodes_config(Config),
+ Nodes=[node()|RemoteNodes],
+ PrivDir=filename:join(?config(priv_dir,Config),""),
+ TracerDataList=lists:map(fun(N)->{N,{file,filename:join([PrivDir,
+ "tf1a_"++
+ atom_to_list(N)
+ ])}} end,
+ Nodes),
+ start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok}]}),
+ Funcs1=activate_global_tracing_regexp(Nodes),
+ deactivate_global_tracing_regexp(Nodes,Funcs1),
+ stop_tracing(Nodes),
+ stop(Nodes),
+ ok.
+%% -----------------------------------------------------------------------------
+
+%% TEST CASE: Basic, distributed, activate global tracing for functions in modules
+%% pointed out using a dir-regexp. No tracing will be done.
+basic_dist_trace_3(suite) -> [];
+basic_dist_trace_3(doc) ->
+ [""];
+basic_dist_trace_3(Config) when is_list(Config) ->
+ RemoteNodes=get_remotenodes_config(Config),
+ Nodes=[node()|RemoteNodes],
+ PrivDir=filename:join(?config(priv_dir,Config),""),
+ TracerDataList=lists:map(fun(N)->{N,{file,filename:join([PrivDir,
+ "tf1b_"++
+ atom_to_list(N)
+ ])}} end,
+ Nodes),
+ start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok}]}),
+ Funcs1=activate_global_tracing_regexp_dir(Nodes),
+ deactivate_global_tracing_regexp_dir(Nodes,Funcs1),
+ stop_tracing(Nodes),
+ stop(Nodes),
+ ok.
+%% -----------------------------------------------------------------------------
+
+%% TEST CASE: Basic, distributed, trace and ti.
+basic_dist_trace_ti_1(suite) -> [];
+basic_dist_trace_ti_1(doc) ->
+ [""];
+basic_dist_trace_ti_1(Config) when is_list(Config) ->
+ RemoteNodes=get_remotenodes_config(Config),
+ Nodes=[node()|RemoteNodes],
+ PrivDir=filename:join(?config(priv_dir,Config),""),
+ TracerDataFun=
+ fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf2_"++atom_to_list(N)])}},
+ {ti,{file,filename:join([PrivDir,"tf2_"++atom_to_list(N)++".ti"])}}]}
+ end,
+ TracerDataList=lists:map(TracerDataFun,Nodes),
+ start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}),
+ activate_local_tracing(Nodes),
+ activate_meta_tracing(Nodes),
+ ?l true=(is_pid(whereis(inviso_rt))),
+ ?l true=(is_pid(whereis(inviso_rt_meta))),
+ deactivate_meta_tracing(Nodes),
+ deactivate_local_tracing(Nodes),
+ stop_tracing(Nodes),
+ ?l true=(is_pid(whereis(inviso_rt))), % Shall still be running.
+ ?l ok=poll(erlang,whereis,[inviso_rt_meta],undefined,3),
+ stop(Nodes),
+ timer:sleep(200), % Give it time to terminate.
+ ?l ok=poll(erlang,whereis,[inviso_rt],undefined,3),% Shall be gone now.
+ ?l undefined=whereis(inviso_rt_meta), % Still gone.
+ ok.
+%% -----------------------------------------------------------------------------
+
+%% Test CASE: Testing that the tpm_tracer functionality works. That is appending
+%% {tracer,Tracer} to a meta match spec.
+basic_dist_trace_ti_2(suite) -> [];
+basic_dist_trace_ti_2(doc) ->
+ [""];
+basic_dist_trace_ti_2(Config) when is_list(Config) ->
+ case erlang:system_info(version) of
+ "5.4"++_ -> % Perhaps not perfect, but work now :-)
+ {skip,"Old emulator"};
+ _ ->
+ basic_dist_trace_ti_2_do(Config)
+ end.
+
+basic_dist_trace_ti_2_do(Config) ->
+ RemoteNodes=get_remotenodes_config(Config),
+ Nodes=[node()|RemoteNodes],
+ PrivDir=filename:join(?config(priv_dir,Config),""),
+ TracerDataFun=
+ fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf3_"++atom_to_list(N)])}},
+ {ti,{file,filename:join([PrivDir,"tf3_"++atom_to_list(N)++".ti"])}}]}
+ end,
+ TracerDataList=lists:map(TracerDataFun,Nodes),
+ start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}),
+ activate_deactivate_meta_tracing_tracer(Nodes),
+ stop_tracing(Nodes),
+ stop(Nodes),
+ ok.
+%% -----------------------------------------------------------------------------
+
+%% TEST CASE: Basic, distributed, trace and ti, where we try to use ctp_all to
+%% check that all global and local patterns are removed but that meta patterns
+%% remain.
+%% This test also checks that if the meta tracer is terminated an error value
+%% is generated when trying to do meta tracing at that node.
+basic_dist_trace_ti_3(suite) -> [];
+basic_dist_trace_ti_3(doc) ->
+ [""];
+basic_dist_trace_ti_3(Config) when is_list(Config) ->
+ RemoteNodes=get_remotenodes_config(Config),
+ Nodes=[node()|RemoteNodes],
+ PrivDir=filename:join(?config(priv_dir,Config),""),
+ TracerDataFun=
+ fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf4_"++atom_to_list(N)])}},
+ {ti,{file,filename:join([PrivDir,"tf4_"++atom_to_list(N)++".ti"])}}]}
+ end,
+ TracerDataList=lists:map(TracerDataFun,Nodes),
+ start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}),
+ activate_local_tracing(Nodes),
+ activate_global_tracing(Nodes),
+ activate_meta_tracing(Nodes),
+ ?l true=(is_pid(whereis(inviso_rt))),
+ ?l true=(is_pid(whereis(inviso_rt_meta))),
+ ?l {ok,NodeResults1}=inviso:ctp_all(Nodes), % Removes local and global patterns.
+ ?l true=check_noderesults(Nodes,ok,NodeResults1),
+ ?l true=check_on_nodes(Nodes,erlang,trace_info,[{code,which,1},traced],{traced,false}),
+ ?l true=check_on_nodes(Nodes,erlang,trace_info,[{code,get_path,0},traced],{traced,false}),
+ %% But meta patters shall remain.
+ ?l true=check_on_nodes(Nodes,
+ erlang,
+ trace_info,
+ [{lists,module_info,0},meta_match_spec],
+ fun({meta_match_spec,L})when length(L)>0 ->true end),
+ ?l true=check_on_nodes(Nodes,
+ erlang,
+ trace_info,
+ [{lists,module_info,0},meta],
+ fun({meta,P})when is_pid(P) ->
+ P=rpc:call(node(P),erlang,whereis,[inviso_rt_meta]),
+ true
+ end),
+ %% Now kill the meta tracer somewhere and try to activate meta tracing.
+ ?l [ANode|_]=Nodes,
+ ?l AMetaPid=rpc:call(ANode,erlang,whereis,[inviso_rt_meta]),
+ ?l rpc:call(ANode,erlang,exit,[AMetaPid,kill]),
+ ?l {ok,NodeResults2}=inviso:tpm(Nodes,math,pi,0,[],void),
+ ?l {value,{ANode,{error,_}}}=lists:keysearch(ANode,1,NodeResults2),
+
+ ?l stop_tracing(Nodes),
+ ?l stop(Nodes),
+ ok.
+%% -----------------------------------------------------------------------------
+
+%% -----------------------------------------------------------------------------
+%% Test cases for SUSPEND
+%% -----------------------------------------------------------------------------
+
+%% TEST CASE: In this test case a trace with ti is started. Trace flags are set,
+%% trace patterns are set and meta trace patterns. We then check that the trace
+%% flags and the meta patterns are removed when tracing suspended.
+%% The suspension is cancelled and we check that it is possible to reactivate
+%% tracing by setting the process flags and meta patterns again.
+suspend_dist_trace_ti_1(suite) -> [];
+suspend_dist_trace_ti_1(doc) ->
+ [""];
+suspend_dist_trace_ti_1(Config) when is_list(Config) ->
+ ?l RemoteNodes=get_remotenodes_config(Config),
+ ?l Nodes=[node()|RemoteNodes],
+ ?l PrivDir=filename:join(?config(priv_dir,Config),""),
+ ?l TracerDataFun=
+ fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf_suspend1_"++atom_to_list(N)])}},
+ {ti,{file,filename:join([PrivDir,"tf_suspend1_"++atom_to_list(N)++".ti"])}}]}
+ end,
+ ?l TracerDataList=lists:map(TracerDataFun,Nodes),
+ start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}),
+ activate_local_tracing(Nodes),
+ activate_meta_tracing(Nodes),
+ ?l true=(is_pid(whereis(inviso_rt))),
+ ?l true=(is_pid(whereis(inviso_rt_meta))),
+ %% Set some trace flags on some newly started test procs.
+ activate_traceflags(Nodes),
+
+ %% Now suspend the tracing on all nodes. That shall result in the removal
+ %% of trace flags and meta trace patterns, but not local trace patterns.
+ ?l {ok,NodeResults1}=inviso:suspend(Nodes,test),
+ ?l true=check_noderesults(Nodes,ok,NodeResults1),
+ %% Trace flags gone?
+ ?l TestProcs=lists:map(fun(N)->rpc:call(N,erlang,whereis,[inviso_test_proc]) end,Nodes),
+ ?l lists:foreach(fun(P)->
+ {flags,[]}=
+ rpc:call(node(P),erlang,trace_info,[P,flags])
+ end,
+ TestProcs),
+ %% Meta patterns shall be gone too, but local functions still there.
+ ?l lists:foreach(fun(N)->
+ {meta,false}=
+ rpc:call(N,
+ erlang,
+ trace_info,
+ [{math,module_info,1},meta]),
+ {traced,local}=
+ rpc:call(N,
+ erlang,
+ trace_info,
+ [{code,which,1},traced])
+ end,
+ Nodes),
+
+ %% Try to activate trace flags, trace patterns and meta tracing while
+ %% suspended. Should not succeed of course!
+ ?l ThisNode=node(),
+ ?l {ok,[{ThisNode,{error,suspended}}]}=
+ inviso:tf([ThisNode],inviso_test_proc,[call]),
+ ?l {ok,[{ThisNode,{error,suspended}}]}=
+ inviso:tpl([ThisNode],math,module_info,1,[]),
+ ?l {ok,[{ThisNode,{error,suspended}}]}=
+ inviso:init_tpm([ThisNode],
+ math,
+ module_info,
+ 1,
+ {?MODULE,tpm_init_func2}, % Does not exist on purpose.
+ {?MODULE,tpm_call_func2}, % Does not exist on purpose.
+ {?MODULE,tpm_return_func2}, % Does not exist on purpose.
+ {?MODULE,tpm_remove_func2}), % Does not exist on purpose.
+
+ %% Now we want to cancel suspension and see that we can reactivate tracing.
+ ?l {ok,NodeResults2}=inviso:cancel_suspension(Nodes),
+ ?l true=check_noderesults(Nodes,ok,NodeResults2),
+
+ ?l {ok,NodeResults3}=
+ inviso:init_tpm(math,
+ module_info,
+ 1,
+ {?MODULE,tpm_init_func2}, % Does not exist on purpose.
+ {?MODULE,tpm_call_func2}, % Does not exist on purpose.
+ {?MODULE,tpm_return_func2}, % Does not exist on purpose.
+ {?MODULE,tpm_remove_func2}), % Does not exist on purpose.
+ ?l true=check_noderesults(Nodes,ok,NodeResults3),
+ ?l {ok,NodeResults5}=
+ inviso:tpm_ms(math,module_info,1,ms1,[{'_',[],[{return_trace}]}]),
+ ?l true=check_noderesults(Nodes,{ok,1},NodeResults5),
+ ?l true=check_on_nodes(Nodes,
+ erlang,
+ trace_info,
+ [{math,module_info,1},meta_match_spec],
+ {meta_match_spec,[{'_',[],[{return_trace}]}]}),
+ ?l {ok,NodeResults6}=inviso:tf(Nodes,inviso_test_proc,[call]),
+ ?l true=check_noderesults(Nodes,{ok,[1]},NodeResults6),
+
+ %deactivate_meta_tracing(Nodes),
+ %deactivate_local_tracing(Nodes),
+ stop_tracing(Nodes),
+ ?l true=(is_pid(whereis(inviso_rt))), % Shall still be running.
+ ?l ok=poll(erlang,whereis,[inviso_rt_meta],undefined,3),
+ stop(Nodes),
+ ?l timer:sleep(200), % Give it time to terminate.
+ ?l ok=poll(erlang,whereis,[inviso_rt],undefined,3),% Shall be gone now.
+ ?l undefined=whereis(inviso_rt_meta), % Still gone.
+ ok.
+%% -----------------------------------------------------------------------------
+
+%% TEST CASE: In this test case a trace with ti is started. Trace flags are set,
+%% trace patterns are set and meta trace patterns. We then suspend tracing at
+%% all nodes, then stop tracing which shall be allowed. We then try to initiate
+%% tracing again which shall not be possible.
+suspend_dist_trace_ti_2(suite) -> [];
+suspend_dist_trace_ti_2(doc) ->
+ [""];
+suspend_dist_trace_ti_2(Config) when is_list(Config) ->
+ ?l RemoteNodes=get_remotenodes_config(Config),
+ ?l Nodes=[node()|RemoteNodes],
+ ?l PrivDir=filename:join(?config(priv_dir,Config),""),
+ ?l TracerDataFun=
+ fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf_suspend2_"++atom_to_list(N)])}},
+ {ti,{file,filename:join([PrivDir,"tf_suspend2_"++atom_to_list(N)++".ti"])}}]}
+ end,
+ ?l TracerDataList=lists:map(TracerDataFun,Nodes),
+ start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}),
+ activate_local_tracing(Nodes),
+ activate_meta_tracing(Nodes),
+ ?l true=(is_pid(whereis(inviso_rt))),
+ ?l true=(is_pid(whereis(inviso_rt_meta))),
+ %% Set some trace flags on some newly started test procs.
+ activate_traceflags(Nodes),
+
+ %% Now suspend the tracing on all nodes. That shall result in the removal
+ %% of trace flags and meta trace patterns, but not local trace patterns.
+ ?l {ok,NodeResults1}=inviso:suspend(Nodes,test),
+ ?l true=check_noderesults(Nodes,ok,NodeResults1),
+
+ %% Now stop tracing.
+ ?l {ok,NodeResults3}=inviso:stop_tracing(Nodes),
+ ?l true=check_noderesults(Nodes,{ok,idle},NodeResults3),
+ %% Now try to initiate tracing again.
+ ThisNode=node(),
+ ?l {ok,[{ThisNode,{error,suspended}}]}=
+ inviso:init_tracing([ThisNode],
+ [{trace,{file,filename:join([PrivDir,"tf_suspend3_"++
+ atom_to_list(ThisNode)])}},
+ {ti,{file,{filename:join([PrivDir,"tf_suspend3_"++
+ atom_to_list(ThisNode)])}}}]),
+
+ %% Cancel the suspension and initiate tracing again.
+ ?l {ok,NodeResults2}=inviso:cancel_suspension(Nodes),
+ ?l true=check_noderesults(Nodes,ok,NodeResults2),
+ ?l TracerDataFun2=
+ fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf_suspend4_"++atom_to_list(N)])}},
+ {ti,{file,filename:join([PrivDir,"tf_suspend4_"++atom_to_list(N)++".ti"])}}]}
+ end,
+ ?l TracerDataList2=lists:map(TracerDataFun2,Nodes),
+ ?l {ok,NodeResults4}=inviso:init_tracing(TracerDataList2),
+ ?l true=check_noderesults(Nodes,{ok,[{trace_log,ok},{ti_log,ok}]},NodeResults4),
+ stop_tracing(Nodes),
+ ?l true=(is_pid(whereis(inviso_rt))), % Shall still be running.
+ stop(Nodes),
+ ?l timer:sleep(200), % Give it time to terminate.
+ ?l ok=poll(erlang,whereis,[inviso_rt],undefined,3),% Shall be gone now.
+ ok.
+%% -----------------------------------------------------------------------------
+
+
+
+%% TEST CASE: This test case tests that the clean function removes (prosumed)
+%% expired data from the internal public-loopdata structure in the inviso_rt_meta
+%% process.
+meta_cleanfunc_dist_1(Config) when is_list(Config) ->
+ RemoteNodes=get_remotenodes_config(Config),
+ Nodes=[node()|RemoteNodes],
+ PrivDir=filename:join(?config(priv_dir,Config),""),
+ TracerDataFun=
+ fun(N)->{N,[{trace,{file,filename:join([PrivDir,"mcf1_"++atom_to_list(N)])}},
+ {ti,{file,filename:join([PrivDir,"mcf1_"++atom_to_list(N)++".ti"])}}]}
+ end,
+ TracerDataList=lists:map(TracerDataFun,Nodes),
+ start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}),
+ %% Now initialize meta tracing, but the call_func is a bit "fixed".
+ ?l {ok,NodeResults1}=
+ inviso:tpm(Nodes,math,module_info,1,[],
+ {?MODULE,meta_cleanfunc_initfunc_1},
+ {?MODULE,meta_cleanfunc_callfunc_1},
+ void,void),
+ ?l true=check_noderesults(Nodes,{ok,1},NodeResults1),
+ %% Nothing in the "our" part of the public loop data.
+ ?l true=check_on_nodes(Nodes,
+ inviso_rt_meta,get_state,[inviso_rt_meta],
+ fun({ok,_LD,{{_,[]},_}})->true end),
+ ?l lists:foreach(fun(N)->rpc:call(N,math,module_info,[exports]) end,Nodes),
+ %% Check that it has been added to the public loopdata structure.
+ ?l true=check_on_nodes(Nodes,
+ ?MODULE,poll,[inviso_rt_meta,
+ get_state,
+ [inviso_rt_meta],
+ fun({ok,_LD,{{_,[{meta_cleanfunc_test1,_Now}]},_}})->
+ true;
+ (_)->false
+ end,
+ 20],
+ ok),
+ %% While we wait for 60 seconds to pass, we test a few other things.
+ ?l {ok,NodeResults2}=
+ inviso:tpm(Nodes,?MODULE,slowfunction2,0,[{'_',[],[{return_trace}]}],
+ {?MODULE,meta_cleanfunc_initfunc_2},
+ {?MODULE,meta_cleanfunc_callfunc_2},
+ {?MODULE,meta_cleanfunc_returnfunc_2},
+ void),
+ ?l true=check_noderesults(Nodes,{ok,1},NodeResults2),
+ ?l lists:foreach(fun(N)->rpc:call(N,?MODULE,slowfunction,[]) end,Nodes),
+ %% Believe it or not but slowfunction is still running, in its own process,
+ %% we are therefore free now to examine the meta tracer.
+ ?l true=check_on_nodes(Nodes,
+ ?MODULE,poll,[inviso_rt_meta,
+ get_state,
+ [inviso_rt_meta],
+ fun({ok,_LD,{{[],Tuples},_}})->
+ {value,_}=
+ lists:keysearch(meta_cleanfunc_test2,
+ 1,
+ Tuples),
+ {value,_}=
+ lists:keysearch(meta_cleanfunc_test1,
+ 1,
+ Tuples),
+ true;
+ (_)->
+ false
+ end,
+ 20],
+ ok),
+ %% Now we wait for slowfunction to return and that the meta_cleanfunc_test2
+ %% to be removed from public loopdata strucuture.
+ ?l timer:sleep(10000),
+ %% The only thing remaining should be the meta_cleanfunc_test1 which will not
+ %% go away for less than that the clean functionality removes it.
+ ?l true=check_on_nodes(Nodes,
+ ?MODULE,poll,[inviso_rt_meta,
+ get_state,
+ [inviso_rt_meta],
+ fun({ok,_LD,{{_,[{meta_cleanfunc_test1,_Now}]},_}})->
+ true;
+ (_)->
+ false
+ end,
+ 20],
+ ok),
+ %% Wait for the clean function to clean meta_cleanfunc_test1 away.
+ ?l timer:sleep(51000), % Shall be gone after 5 seconds.
+ ?l true=check_on_nodes(Nodes,
+ ?MODULE,poll,[inviso_rt_meta,
+ get_state,
+ [inviso_rt_meta],
+ fun({ok,_LD,{{_,[]},_}})->true;
+ (_)->false
+ end,
+ 20],
+ ok),
+ stop_tracing(Nodes),
+ stop(Nodes),
+ ok.
+
+%% This function acts as tpm initialization function when we are going to test
+%% that the clean function works. Note that we here assume standard public loop
+%% datastructure.
+meta_cleanfunc_initfunc_1(_M,_F,_Arity,{E1,_E2}) ->
+ {ok,{E1,[]},void}.
+%% Function that is supposed to be called when the meta traced function is
+%% called.
+meta_cleanfunc_callfunc_1(_Pid,_Args,{{E1,E2},Global}) ->
+ {ok,{{E1,[{meta_cleanfunc_test1,now()}|E2]},Global},void}.
+
+meta_cleanfunc_initfunc_2(_M,_F,_Arity,PublLD) ->
+ {ok,PublLD,void}.
+meta_cleanfunc_callfunc_2(_Pid,_Args,{{E1,E2},Global}) ->
+ {ok,{{E1,[{meta_cleanfunc_test2,now()}|E2]},Global},void}.
+meta_cleanfunc_returnfunc_2(_Pid,_,{{E1,E2},Global}) ->
+ {value,_}=lists:keysearch(meta_cleanfunc_test2,1,E2),
+ {ok,{{E1,lists:keydelete(meta_cleanfunc_test2,1,E2)},Global},void}.
+
+slowfunction() ->
+ spawn(?MODULE,slowfunction1,[]).
+slowfunction1() ->
+ slowfunction2(). % Meta trace on this function call.
+slowfunction2() ->
+ timer:sleep(2000),
+ true.
+%% -----------------------------------------------------------------------------
+
+%% TEST CASE: Testing that a runtime component can be started instructing it
+%% to use a handler fun. Checks that the handler fun is called if a trace
+%% message comes in.
+basic_handlerfun_dist_1(suite) -> [];
+basic_handlerfun_dist_1(doc) ->
+ [""];
+basic_handlerfun_dist_1(Config) when is_list(Config) ->
+ RemoteNodes=get_remotenodes_config(Config),
+ Nodes=[node()|RemoteNodes],
+ ?l lists:foreach(fun(N)->rpc:call(N,ets,insert,[inviso_sideeffect_tab,{bhf1,0}]) end,
+ Nodes),
+ TracerDataFun=
+ fun(N)->{N,{fun basic_handlerfun_dist_1_fun/2,inviso_sideeffect_tab}} end,
+ TracerDataList=lists:map(TracerDataFun,Nodes),
+ start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok}]}),
+ activate_local_tracing(Nodes),
+ activate_traceflags(Nodes),
+ ?l lists:foreach(fun(N)->[{bhf1,0}]=
+ rpc:call(N,ets,lookup,[inviso_sideeffect_tab,bhf1])
+ end,
+ Nodes),
+ ?l inviso_test_proc ! {apply,code,which,[lists]},
+ ok=poll(ets,lookup,[inviso_sideeffect_tab,bhf1],[{bhf1,1}],20),
+ deactivate_traceflags(Nodes),
+ deactivate_local_tracing(Nodes),
+ stop_tracing(Nodes),
+ timer:sleep(100),
+ ?l [{bhf1,1}]=ets:lookup(inviso_sideeffect_tab,bhf1),
+ stop(Nodes),
+ ok.
+
+%% Function used as handler fun for testcase above.
+basic_handlerfun_dist_1_fun(_Msg,TId) ->
+ ets:update_counter(TId,bhf1,1),
+ TId.
+%% -----------------------------------------------------------------------------
+
+%% TEST CASE: Here we test that delete_log removes the files at the involved
+%% runtime nodes. In this case we test that we remove logs according to last
+%% used tracer data.
+delete_log_dist_1(suite) -> [];
+delete_log_dist_1(doc) -> [""];
+delete_log_dist_1(Config) when is_list(Config) ->
+ RemoteNodes=get_remotenodes_config(Config),
+ Nodes=[node()|RemoteNodes],
+ PrivDir=filename:join(?config(priv_dir,Config),""),
+ TracerDataFun=
+ fun(N)->{N,[{trace,{file,filename:join([PrivDir,"dl1_"++atom_to_list(N)])}},
+ {ti,{file,filename:join([PrivDir,"dl1_"++atom_to_list(N)++".ti"])}}]}
+ end,
+ TracerDataList=lists:map(TracerDataFun,Nodes),
+ start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}),
+ ?l Files=lists:map(fun({N,TD})->
+ ?l {value,{_,{_,TraceFile}}}=lists:keysearch(trace,1,TD),
+ ?l {value,{_,{_,TiFile}}}=lists:keysearch(ti,1,TD),
+ ?l {N,{TraceFile,TiFile}}
+ end,
+ TracerDataList),
+ io:format("The Files is:~w~n",[Files]),
+ ?l {ok,NodeResults1}=inviso:delete_log(Nodes), % Should not work!
+ ?l true=check_noderesults(Nodes,{error,tracing},NodeResults1),
+ stop_tracing(Nodes),
+ %% Files still here.
+ ?l lists:foreach(fun({N,{F1,F2}})->
+ ?l {ok,_}=rpc:call(N,file,read_file_info,[F1]),
+ ?l {ok,_}=rpc:call(N,file,read_file_info,[F2])
+ end,
+ Files),
+ ?l {ok,NodeResults2}=inviso:delete_log(Nodes),
+ ?l true=check_noderesults(Nodes,
+ fun({_N,{ok,LogInfos}})->
+ ?l {value,{_,[{ok,_FName1}]}}=
+ lists:keysearch(trace_log,1,LogInfos),
+ ?l {value,{_,[{ok,_FName2}]}}=
+ lists:keysearch(ti_log,1,LogInfos),
+ true
+ end,
+ NodeResults2),
+ %% The files shall be gone now.
+ ?l lists:foreach(fun({N,{F1,F2}})->
+ ?l {error,enoent}=rpc:call(N,file,read_file_info,[F1]),
+ ?l {error,enoent}=rpc:call(N,file,read_file_info,[F2])
+ end,
+ Files),
+ stop(Nodes),
+ ok.
+%% -----------------------------------------------------------------------------
+
+
+%% TEST CASE: Test of the autostart behaviour of the runtime component.
+%% Here we test that a runtime component is started according to the autostart.conf
+%% file. Note that the repeat parameter is set to 2.
+autostart_dist_1(suite) -> [];
+autostart_dist_1(doc) ->
+ [""];
+autostart_dist_1(Config) when is_list(Config) ->
+ RemoteNodes=get_remotenodes_config(Config),
+ PrivDir=filename:join(?config(priv_dir,Config),""),
+ AutoConfFile=filename:join(PrivDir,"autostart1.conf"),
+ [RNode|_]=RemoteNodes,
+ ?l ok=rpc:call(RNode,application,stop,[runtime_tools]),
+ ?l ok=rpc:call(RNode,application,set_env,[runtime_tools,
+ inviso_autostart_conf,
+ AutoConfFile]),
+ ?l {ok,FD}=file:open(AutoConfFile,[write]),
+ ?l ok=io:format(FD,"~w.~n~w.~n",[{repeat,2},{tag,c_ref}]),
+ ?l file:close(FD),
+ ?l ok=rpc:call(RNode,application,start,[runtime_tools]),
+ timer:sleep(1000),
+ ?l P1=rpc:call(RNode,erlang,whereis,[inviso_rt]),
+ ?l true=is_pid(P1),
+ ?l rpc:call(RNode,erlang,exit,[P1,kill]),
+ ?l ok=rpc:call(RNode,application,stop,[runtime_tools]),
+ ?l ok=rpc:call(RNode,application,start,[runtime_tools]),
+ timer:sleep(1000),
+ ?l P2=rpc:call(RNode,erlang,whereis,[inviso_rt]),
+ ?l true=is_pid(P2),
+ ?l rpc:call(RNode,erlang,exit,[P2,kill]),
+ ?l ok=rpc:call(RNode,application,stop,[runtime_tools]),
+ ?l ok=rpc:call(RNode,application,start,[runtime_tools]),
+ timer:sleep(1000),
+ ?l undefined=rpc:call(RNode,erlang,whereis,[inviso_rt]),
+ ok.
+%% -----------------------------------------------------------------------------
+
+%% TEST CASE: Test of autostart. Here we focus on that an autostarted
+%% runtime component actually follows the trace case command file and
+%% initiates tracing.
+autostart_dist_2(suite) -> [];
+autostart_dist_2(doc) ->
+ [""];
+autostart_dist_2(Config) when is_list(Config) ->
+ RemoteNodes=get_remotenodes_config(Config),
+ PrivDir=filename:join(?config(priv_dir,Config),""),
+ AutoConfFile=filename:join(PrivDir,"autostart2.conf"),
+ [RNode|_]=RemoteNodes,
+ ?l ok=rpc:call(RNode,application,stop,[runtime_tools]),
+ ?l ok=rpc:call(RNode,application,set_env,[runtime_tools,
+ inviso_autostart_conf,
+ AutoConfFile]),
+ ?l CmdFileName=filename:join(PrivDir,"autostart_cmd_as1"),
+ ?l {ok,FD}=file:open(CmdFileName,[write]),
+ ?l ok=io:format(FD,
+ "inviso:tpl(Nodes,M,F,Arity,[]).~n"
+ "inviso:tf(Nodes,inviso_test_proc,[call]).~n",
+ []),
+ ?l file:close(FD),
+ ?l TraceFileName=filename:join([PrivDir,"as1_"++atom_to_list(RNode)]),
+ ?l TiFileName=filename:join([PrivDir,"as1_"++atom_to_list(RNode)++".ti"]),
+ ?l inviso_as_lib:setup_autostart(RNode,
+ 2,
+ [],
+ [{trace,{file,TraceFileName}},
+ {ti,{file,TiFileName}}],
+ [[CmdFileName]],
+ [{'M',code},{'F',which},{'Arity',1}],
+ [{{inviso,tpl,5},{inviso_rt,tpl,{erlang,tl}}},
+ {{inviso,tf,3},{inviso_rt,tf,{erlang,tl}}}]),
+ ?l TestP=spawn(RNode,?MODULE,test_proc_init,[]),
+ ?l ok=rpc:call(RNode,application,start,[runtime_tools]),
+ ?l timer:sleep(1000),
+ ?l {ok,_}=file:read_file_info(TraceFileName),
+ ?l {ok,_}=file:read_file_info(TiFileName),
+ ?l true=is_pid(P=rpc:call(RNode,erlang,whereis,[inviso_rt])),
+ ?l ok=poll(rpc,call,[RNode,erlang,trace_info,[{code,which,1},traced]],{traced,local},10),
+ ?l {flags,[call]}=rpc:call(RNode,erlang,trace_info,[TestP,flags]),
+ ?l rpc:call(RNode,erlang,exit,[P,kill]),
+ ok.
+%% -----------------------------------------------------------------------------
+
+%% TEST CASE: Here we test that an autostarted runtime component with a dependency
+%% to a specific control component tries to connect to that control component
+%% during its start-up.
+autostart_dist_3(suite) -> [];
+autostart_dist_3(doc) ->
+ [""];
+autostart_dist_3(Config) when is_list(Config) ->
+ RemoteNodes=get_remotenodes_config(Config),
+ PrivDir=filename:join(?config(priv_dir,Config),""),
+ AutoConfFile=filename:join(PrivDir,"autostart3.conf"),
+ [RNode|_]=RemoteNodes,
+ ?l ok=rpc:call(RNode,application,stop,[runtime_tools]),
+ ?l ok=rpc:call(RNode,application,set_env,[runtime_tools,
+ inviso_autostart_conf,
+ AutoConfFile]),
+ ?l {ok,FD}=file:open(AutoConfFile,[write]),
+ ?l ok=io:format(FD,"~w.~n~w.~n~w.~n",
+ [{options,[{dependency,{infinity,node()}}]},{repeat,2},{tag,c_ref}]),
+ ?l file:close(FD),
+ %% Now start inviso at this node here for the runtime to connect.
+ ?l {ok,_Pid}=inviso:start(),
+ ?l ok=poll(erlang,whereis,[inviso_c],fun(P) when is_pid(P)->true;(_)->false end,10),
+ %% Make the runtime component start.
+ ?l ok=rpc:call(RNode,application,start,[runtime_tools]),
+ ?l ok=poll(rpc,call,[RNode,erlang,whereis,[inviso_rt]],
+ fun(P) when is_pid(P)->true;(_)->false end,10),
+ %% Check that the runtime component started.
+ ?l ok=poll(inviso,get_status,[[RNode]],{ok,[{RNode,{ok,{new,running}}}]},20),
+% ?l {ok,[{RNode,{ok,{new,running}}}]}=inviso:get_status([RNode]),
+ stop([RNode]),
+ ok.
+%% -----------------------------------------------------------------------------
+
+
+
+%% TEST CASE: Test of the dependency mechanism in the runtime component.
+%% Default behaviour is dependency=infinity, i.e the runtime components remains.
+%% We also test here that we can reconnect to the runtime.
+running_alone_dist_1(suite) -> [];
+running_alone_dist_1(doc) ->
+ [""];
+running_alone_dist_1(Config) when is_list(Config) ->
+ ?l {ok,_Pid1}=inviso:start(), % Start a control component.
+ RemoteNodes=get_remotenodes_config(Config),
+ Nodes=[node()|RemoteNodes],
+ ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref,[]),
+ ?l true=check_noderesults(Nodes,{ok,new},NodeResults1),
+ ?l shutdown=inviso:stop(), % Stop the control component!
+ ?l undefined=whereis(inviso_c),
+ timer:sleep(3000), % How long shall we wait? :-)
+ ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt])) end,
+ Nodes),
+ ?l {ok,_Pid2}=inviso:start(),
+ ?l {ok,NodeResults2}=inviso:add_nodes(Nodes,b_ref,[]),
+ ?l true=check_noderesults(Nodes,{ok,{adopted,new,running,a_ref}},NodeResults2),
+ stop(Nodes),
+ ok.
+%% -----------------------------------------------------------------------------
+
+%% TEST CASE: Test of the dependency mechanism in the runtime component.
+%% Test that the runtime components terminates after the specified 5000 ms.
+running_alone_dist_2(suite) -> [];
+running_alone_dist_2(doc) ->
+ [""];
+running_alone_dist_2(Config) when is_list(Config) ->
+ ?l {ok,_Pid1}=inviso:start(), % Start a control component.
+ RemoteNodes=get_remotenodes_config(Config),
+ Nodes=[node()|RemoteNodes],
+ ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref,[{dependency,5000}]),
+ ?l true=check_noderesults(Nodes,{ok,new},NodeResults1),
+ ?l shutdown=inviso:stop(), % Stop the control component!
+ ?l undefined=whereis(inviso_c),
+ timer:sleep(2000),
+ ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt])) end,
+ Nodes),
+ timer:sleep(4000), % Now they shall be dead!
+ ?l lists:foreach(fun(N)->undefined=rpc:call(N,erlang,whereis,[inviso_rt]) end,
+ Nodes),
+ ok.
+%% -----------------------------------------------------------------------------
+
+%% TEST CASE: Test of the dependency mechanism in the runtime component.
+%% Test that the runtime components terminates after the specified 5000 ms.
+running_alone_dist_3(suite) -> [];
+running_alone_dist_3(doc) ->
+ [""];
+running_alone_dist_3(Config) when is_list(Config) ->
+ ?l {ok,_Pid1}=inviso:start(), % Start a control component.
+ RemoteNodes=get_remotenodes_config(Config),
+ Nodes=[node()|RemoteNodes],
+ ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref,[{dependency,1000}]),
+ ?l true=check_noderesults(Nodes,{ok,new},NodeResults1),
+ ?l {ok,NodeResults2}=inviso:change_options(Nodes,[{dependency,5000}]),
+ ?l true=check_noderesults(Nodes,ok,NodeResults2),
+ ?l shutdown=inviso:stop(), % Stop the control component!
+ ?l undefined=whereis(inviso_c),
+ timer:sleep(3000),
+ ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt])) end,
+ Nodes),
+ timer:sleep(3000), % Now they shall be dead!
+ ?l lists:foreach(fun(N)->undefined=rpc:call(N,erlang,whereis,[inviso_rt]) end,
+ Nodes),
+ ok.
+%% -----------------------------------------------------------------------------
+
+%% TEST CASE: Test of the dependency mechanism in the runtime component.
+%% Test that the runtime components terminates after the specified 5000 ms,
+%% like we did in running_alone_dist_2. But now we also start tracing and checks
+%% that all inviso processes actually disappears when the time-out is reached.
+running_alone_dist_4(suite) -> [];
+running_alone_dist_4(doc) ->
+ [""];
+running_alone_dist_4(Config) when is_list(Config) ->
+ RemoteNodes=get_remotenodes_config(Config),
+ Nodes=[node()|RemoteNodes],
+ %% Start some tracing!
+ PrivDir=filename:join(?config(priv_dir,Config),""),
+ TracerDataFun=
+ fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf_ra4"++atom_to_list(N)])}},
+ {ti,{file,filename:join([PrivDir,"tf_ra4_"++atom_to_list(N)++".ti"])}}]}
+ end,
+ TracerDataList=lists:map(TracerDataFun,Nodes),
+ start_and_init_tracing2(Nodes,
+ [{dependency,5000}],
+ TracerDataList,
+ {ok,[{trace_log,ok},{ti_log,ok}]}),
+
+ ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt])) end,
+ Nodes),
+ ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt_meta])) end,
+ Nodes),
+ %% Stop control component and wait for the runtimes to terminate after
+ %% running alone timer has expired.
+ ?l shutdown=inviso:stop(), % Stop the control component!
+ ?l undefined=whereis(inviso_c),
+ timer:sleep(2000),
+ ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt])) end,
+ Nodes),
+ ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt_meta])) end,
+ Nodes),
+ timer:sleep(4000), % Now they shall be dead!
+ ?l lists:foreach(fun(N)->undefined=rpc:call(N,erlang,whereis,[inviso_rt]) end,
+ Nodes),
+ ?l lists:foreach(fun(N)->undefined=rpc:call(N,erlang,whereis,[inviso_rt_meta]) end,
+ Nodes),
+ ok.
+%% -----------------------------------------------------------------------------
+
+%% TEST CASE: Test of the dependency mechanism in the runtime component.
+%% Test that the runtime components terminates imeediately when the control
+%% component is stopped. Check that all processes are gone.
+running_alone_dist_5(suite) -> [];
+running_alone_dist_5(doc) ->
+ [""];
+running_alone_dist_5(Config) when is_list(Config) ->
+ RemoteNodes=get_remotenodes_config(Config),
+ Nodes=[node()|RemoteNodes],
+ %% Start some tracing!
+ PrivDir=filename:join(?config(priv_dir,Config),""),
+ TracerDataFun=
+ fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf_ra5"++atom_to_list(N)])}},
+ {ti,{file,filename:join([PrivDir,"tf_ra5_"++atom_to_list(N)++".ti"])}}]}
+ end,
+ TracerDataList=lists:map(TracerDataFun,Nodes),
+ start_and_init_tracing2(Nodes,
+ [{dependency,0}],
+ TracerDataList,
+ {ok,[{trace_log,ok},{ti_log,ok}]}),
+
+ ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt])) end,
+ Nodes),
+ ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt_meta])) end,
+ Nodes),
+ %% Stop control component and check that all runtime component processes have
+ %% terminate more or less immediately afterwards, since dependency==0.
+ ?l shutdown=inviso:stop(), % Stop the control component!
+ timer:sleep(100),
+ ?l undefined=whereis(inviso_c),
+ timer:sleep(500),
+ ?l lists:foreach(fun(N)->undefined=rpc:call(N,erlang,whereis,[inviso_rt]) end,
+ Nodes),
+ ?l lists:foreach(fun(N)->undefined=rpc:call(N,erlang,whereis,[inviso_rt_meta]) end,
+ Nodes),
+ ok.
+%% -----------------------------------------------------------------------------
+
+%% TEST CASE: Test of the overload protection mechanism. The mechanism checks
+%% for overload using the callback approximately at the interval specified.
+%% Check that it does not start protection until start of tracing.
+overload_dist_1(suite) -> [];
+overload_dist_1(doc) ->
+ [""];
+overload_dist_1(Config) when is_list(Config) ->
+ ?l {ok,_Pid1}=inviso:start(), % Start a control component.
+ RemoteNodes=get_remotenodes_config(Config),
+ Nodes=[node()|RemoteNodes],
+ ?l lists:foreach(fun(N)->true=rpc:call(N,ets,insert,[inviso_sideeffect_tab,{ovl1,0}]) end,
+ Nodes), % Initiate the counter.
+ ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,
+ a_ref,
+ [{overload,{{?MODULE,overload1},500}}]),
+ ?l true=check_noderesults(Nodes,{ok,new},NodeResults1),
+ timer:sleep(1000), % Give the loadcheck time to perform.
+ ?l [{_,0}]=ets:lookup(inviso_sideeffect_tab,ovl1), % Nothing should have happened.
+
+ %% Overload check shall not start until we start tracing.
+ PrivDir=filename:join(?config(priv_dir,Config),""),
+ TracerDataList=lists:map(fun(N)->{N,[{trace,
+ {file,filename:join([PrivDir,
+ "tf_ovl1."++atom_to_list(N)
+ ])}}]}
+ end,
+ Nodes),
+ ?l {ok,NodeResults2}=inviso:init_tracing(TracerDataList),
+ ?l true=check_noderesults(Nodes,{ok,[{trace_log,ok}]},NodeResults2),
+ timer:sleep(1500), % Give the loadcheck time to perform.
+ ?l [{_,N}]=ets:lookup(inviso_sideeffect_tab,ovl1),
+ ?l true=(N>=2), % After 1,5 seconds, at least 2 checks.
+
+ %% Now change options and remove overload checking!
+ ?l {ok,NodeResults3}=inviso:change_options(Nodes,[overload]),
+ ?l true=check_noderesults(Nodes,ok,NodeResults3),
+ ?l [{_,N2}]=ets:lookup(inviso_sideeffect_tab,ovl1),
+ timer:sleep(1000),
+ ?l [{_,N2}]=ets:lookup(inviso_sideeffect_tab,ovl1), % No more loadchecks!
+
+ stop_tracing(Nodes),
+ stop(Nodes),
+ ok.
+%% -----------------------------------------------------------------------------
+
+%% TEST CASE: Test of the overload protection mechanism. In this case we focus
+%% in that the init and remove functions are carried out at change_options and
+%% when starting and stoping the runtime component.
+overload_dist_2(suite) -> [];
+overload_dist_2(doc) ->
+ [""];
+overload_dist_2(Config) when is_list(Config) ->
+ ?l {ok,_Pid1}=inviso:start(), % Start a control component.
+ RemoteNodes=get_remotenodes_config(Config),
+ Nodes=[node()|RemoteNodes],
+ ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,
+ a_ref,
+ [{overload,{{?MODULE,overload2},
+ 500,
+ {?MODULE,overload2i,[]},
+ {?MODULE,overload2r,[]}}}]),
+ ?l true=check_noderesults(Nodes,{ok,new},NodeResults1),
+ ?l [{_,0}]=ets:lookup(inviso_sideeffect_tab,ovl2),
+
+ PrivDir=filename:join(?config(priv_dir,Config),""),
+ TracerDataList=lists:map(fun(N)->{N,[{trace,
+ {file,filename:join([PrivDir,
+ "tf_ovl2."++atom_to_list(N)
+ ])}}]}
+ end,
+ Nodes),
+ ?l {ok,NodeResults2}=inviso:init_tracing(TracerDataList),
+ ?l true=check_noderesults(Nodes,{ok,[{trace_log,ok}]},NodeResults2),
+ timer:sleep(1500), % Give the loadcheck time to perform.
+ ?l [{_,N}]=ets:lookup(inviso_sideeffect_tab,ovl2),
+ io:format("� is:~p~n",[N]),
+ ?l true=(N>=2), % After 1,5 seconds, at least 2 checks.
+ ?l {ok,NodeResults3}=inviso:change_options(Nodes,[{overload,{{?MODULE,overload3},
+ 500,
+ {?MODULE,overload3i,[]},
+ {?MODULE,overload3r,[]}}}]),
+ ?l true=check_noderesults(Nodes,ok,NodeResults3),
+ ?l []=ets:lookup(inviso_sideeffect_tab,ovl2),
+ timer:sleep(1500),
+ ?l [{_,N2}]=ets:lookup(inviso_sideeffect_tab,ovl3),
+ ?l true=(N2>=2), % After 1,5 seconds, at least 2 checks.
+ stop_tracing(Nodes),
+ ?l []=ets:lookup(inviso_sideeffect_tab,ovl3r), % Remove function shall not be called.
+ ?l [{_,N3}]=ets:lookup(inviso_sideeffect_tab,ovl3),
+ timer:sleep(1000), % Check that overloadchecking has stopped.
+ ?l [{_,N3}]=ets:lookup(inviso_sideeffect_tab,ovl3),
+ stop(Nodes),
+ ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,ovl3r],[{ovl3r,done}],20),
+ ok.
+%% -----------------------------------------------------------------------------
+
+%% TEST CASE: Test of the overload protections mechanism. Here we focus on testing
+%% that if overload is reached tracing is really suspended.
+overload_dist_3(suite) -> [];
+overload_dist_3(doc) ->
+ [""];
+overload_dist_3(Config) when is_list(Config) ->
+ RemoteNodes=get_remotenodes_config(Config),
+ Nodes=[node()|RemoteNodes],
+ PrivDir=filename:join(?config(priv_dir,Config),""),
+ TracerDataList=
+ lists:map(fun(N)->{N,[{trace,{file,filename:join([PrivDir,
+ "tf_ovl3."++atom_to_list(N)])}},
+ {ti,{file,filename:join([PrivDir,
+ "tf_ovl3_ti."++atom_to_list(N)])}}]}
+ end,
+ Nodes),
+ ?l lists:foreach(fun(N)->
+ true=rpc:call(N,ets,insert,[inviso_sideeffect_tab,{ovl4,0}])
+ end,
+ Nodes),
+ start_and_init_tracing2(Nodes,
+ [{overload,{{?MODULE,overload4},500}}],
+ TracerDataList,
+ {ok,[{trace_log,ok},{ti_log,ok}]}),
+ activate_local_tracing(Nodes),
+ activate_meta_tracing(Nodes),
+ activate_traceflags(Nodes),
+ timer:sleep(600),
+ ?l [{_,N1}]=ets:lookup(inviso_sideeffect_tab,ovl4),
+ ?l true=(N1>=1), % Overload check has been done!
+ ?l Node=node(),
+ ?l {ok,[{Node,{ok,{tracing,running}}}]}=inviso:get_status([node()]),
+ ?l true=ets:insert(inviso_sideeffect_tab,{ovl4_suspend,true}),
+ timer:sleep(600),
+ ?l {ok,[{Node,{ok,{tracing,{suspended,test}}}}]}=inviso:get_status([node()]),
+ ?l [{_,N2}]=ets:lookup(inviso_sideeffect_tab,ovl4),
+ ?l {flags,[]}=erlang:trace_info(whereis(inviso_test_proc),flags),
+ ?l {meta,false}=erlang:trace_info({lists,module_info,0},meta),
+ ?l {traced,local}=erlang:trace_info({code,which,1},traced),
+ ?l true=(is_pid(whereis(inviso_rt_meta))),
+ ?l true=ets:delete(inviso_sideeffect_tab,ovl4_suspend),
+ timer:sleep(600),
+ ?l [{_,N2}]=ets:lookup(inviso_sideeffect_tab,ovl4), % No checking while suspended!
+ ?l {ok,[{Node,ok}]}=inviso:cancel_suspension([node()]),
+ ?l {ok,NodeResults1}=inviso:get_status(Nodes),
+ ?l true=check_noderesults(Nodes,{ok,{tracing,running}},NodeResults1),
+ timer:sleep(600),
+ ?l [{_,N3}]=ets:lookup(inviso_sideeffect_tab,ovl4),
+ ?l true=(N3>N2),
+ ?l deactivate_local_tracing(Nodes),
+ ?l stop_tracing(Nodes),
+ ?l stop(Nodes),
+ ok.
+%% -----------------------------------------------------------------------------
+
+%% TEST CASE. Test that the overload mechanism is triggered by to the runtime
+%% component incomming messages, and nothing else.
+overload_dist_4(suite) -> [];
+overload_dist_4(doc) ->
+ [""];
+overload_dist_4(Config) when is_list(Config) ->
+ ?l {ok,_Pid1}=inviso:start(), % Start a control component.
+ RemoteNodes=get_remotenodes_config(Config),
+ Nodes=[node()|RemoteNodes],
+ ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,
+ a_ref,
+ [{overload,{{?MODULE,overload5},
+ infinity,
+ {?MODULE,overload5i,[]},
+ {?MODULE,overload5r,[]}}}]),
+ ?l true=check_noderesults(Nodes,{ok,new},NodeResults1),
+ ?l [{_,0}]=ets:lookup(inviso_sideeffect_tab,ovl5),
+
+ PrivDir=filename:join(?config(priv_dir,Config),""),
+ TracerDataList=lists:map(fun(N)->{N,[{trace,
+ {file,filename:join([PrivDir,
+ "tf_ovl4."++atom_to_list(N)
+ ])}}]}
+ end,
+ Nodes),
+ ?l {ok,NodeResults2}=inviso:init_tracing(TracerDataList),
+ ?l true=check_noderesults(Nodes,{ok,[{trace_log,ok}]},NodeResults2),
+ timer:sleep(2000), % Give the loadcheck time to perform.
+ ?l [{_,N}]=ets:lookup(inviso_sideeffect_tab,ovl5),
+ ?l true=(N==0), % And nothing shall have happend!
+ %% Now we send a message to the inviso_rt, then the load check function
+ %% shall be called.
+ ?l whereis(inviso_rt) ! test_of_loadcheck,
+ timer:sleep(200), % Make sure the inviso_rt gets scheduled.
+ ?l [{_,1}]=ets:lookup(inviso_sideeffect_tab,ovl5),
+ stop_tracing(Nodes),
+ ?l []=ets:lookup(inviso_sideeffect_tab,ovl5r), % Remove function shall not be called.
+ ?l [{_,N3}]=ets:lookup(inviso_sideeffect_tab,ovl5),
+ ?l whereis(inviso_rt) ! test_of_loadcheck,
+ timer:sleep(1000), % Check that overloadchecking has stopped.
+ ?l [{_,N3}]=ets:lookup(inviso_sideeffect_tab,ovl5),
+ stop(Nodes),
+ ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,ovl5r],[{ovl5r,done}],20),
+ ok.
+%% -----------------------------------------------------------------------------
+
+%% TEST CASE. Test that the overload mechanism correctly calculates remaining time
+%% to next load check if a message comes into the runtime component "interupting"
+%% the waiting for loadcheck timeout. (Loadcheck timeout is implemented as an after
+%% in the receive).
+overload_dist_5(suite) -> [];
+overload_dist_5(doc) ->
+ [""];
+overload_dist_5(Config) when is_list(Config) ->
+ ?l {ok,_Pid1}=inviso:start(), % Start a control component.
+ RemoteNodes=get_remotenodes_config(Config),
+ Nodes=[node()|RemoteNodes],
+ ?l lists:foreach(fun(N)->true=rpc:call(N,ets,insert,[inviso_sideeffect_tab,{ovl6,0}]) end,
+ Nodes), % Initiate the counter.
+ ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,
+ a_ref,
+ [{overload,{{?MODULE,overload6},1000}}]),
+ ?l true=check_noderesults(Nodes,{ok,new},NodeResults1),
+ %% Overload check shall not start until we start tracing.
+ PrivDir=filename:join(?config(priv_dir,Config),""),
+ TracerDataList=lists:map(fun(N)->{N,[{trace,
+ {file,filename:join([PrivDir,
+ "tf_ovl5."++atom_to_list(N)
+ ])}}]}
+ end,
+ Nodes),
+ ?l {ok,NodeResults2}=inviso:init_tracing(TracerDataList),
+ ?l true=check_noderesults(Nodes,{ok,[{trace_log,ok}]},NodeResults2),
+ ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,ovl6],[{ovl6,2}],25),
+ %% Now we know that exactly 2 checks have been made. Try to Distract the runtime :-)
+ ?l inviso_rt:state(whereis(inviso_rt)), % Make it have to receive a message.
+ timer:sleep(500),
+ ?l [{_,2}]=ets:lookup(inviso_sideeffect_tab,ovl6), % Should still be 2.
+ timer:sleep(600),
+ ?l [{_,3}]=ets:lookup(inviso_sideeffect_tab,ovl6), % We expect yet one check.
+ timer:sleep(1100),
+ ?l [{_,4}]=ets:lookup(inviso_sideeffect_tab,ovl6),
+
+ stop_tracing(Nodes),
+ stop(Nodes),
+ ok.
+%% -----------------------------------------------------------------------------
+
+
+%% TEST CASE: Test of the subscription mechanism.
+subscribe_dist_1(Config) when is_list(Config) ->
+ RemoteNodes=get_remotenodes_config(Config),
+ Nodes=[node()|RemoteNodes],
+ PrivDir=filename:join(?config(priv_dir,Config),""),
+ Pid=spawn(?MODULE,inviso_msg_collector,[]),
+ CtrlPid=whereis(inviso_c),
+
+ ?l {ok,_Pid}=inviso:start(), % Start a control component.
+ ?l ok=inviso:subscribe(Pid),
+ ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref,[]),
+ ?l true=check_noderesults(Nodes,{ok,new},NodeResults1),
+ ?l {ok,NodeResults2}=inviso:get_status(Nodes),
+ ?l true=check_noderesults(Nodes,{ok,{new,running}},NodeResults2),
+ check_msg_collector(Nodes,
+ fun({inviso_event,CP,_,{connected,N,{_Tag,{idle,running}}}})
+ when CP==CtrlPid ->
+ {true,N};
+ (_) ->
+ false
+ end,
+ 13),
+ TracerDataList=lists:map(fun(N)->{N,{file,
+ filename:join([PrivDir,
+ "tf_sub1"++atom_to_list(N)])}}
+ end,
+ Nodes),
+ ?l {ok,NodeResults3}=inviso:init_tracing(TracerDataList),
+ ?l true=check_noderesults(Nodes,{ok,[{trace_log,ok}]},NodeResults3),
+ check_msg_collector(Nodes,
+ fun({inviso_event,CP,_,{state_change,N,{tracing,running}}})
+ when CP==CtrlPid ->
+ {true,N};
+ (_) ->
+ false
+ end,
+ 13),
+ ?l {ok,NodeResults4}=inviso:suspend(Nodes,test),
+ ?l true=check_noderesults(Nodes,ok,NodeResults4),
+ check_msg_collector(Nodes,
+ fun({inviso_event,CP,_,{state_change,N,{tracing,{suspended,test}}}})
+ when CP==CtrlPid ->
+ {true,N};
+ (_) ->
+ false
+ end,
+ 13),
+ ?l [RNode|_]=RemoteNodes,
+ ?l RInvisoPid=rpc:call(RNode,erlang,whereis,[inviso_rt]),
+ ?l rpc:call(RNode,erlang,exit,[RInvisoPid,kill]),
+ check_msg_collector([RNode],
+ fun({inviso_event,CP,_,{disconnected,N,_Info}})
+ when CP==CtrlPid ->
+ {true,N};
+ (_) ->
+ false
+ end,
+ 11),
+
+ ?l {ok,_NodeResults5}=inviso:stop_tracing(Nodes),
+ ?l {ok,_NodeResults6}=inviso:stop_nodes(Nodes),
+ ?l shutdown=inviso:stop(),
+ ok.
+%% -----------------------------------------------------------------------------
+
+
+%% TEST CASE: fetch_log test of single straight trace_log file in distributed
+%% environment.
+fetch_log_dist_trace_1(suite) -> [];
+fetch_log_dist_trace_1(doc) ->
+ ["fetch_log test of single straight trace_log file in distributed"
+ "environment."];
+fetch_log_dist_trace_1(Config) when is_list(Config) ->
+ RemoteNodes=get_remotenodes_config(Config),
+ Nodes=[node()|RemoteNodes],
+ PrivDir=filename:join(?config(priv_dir,Config),""),
+ TracerDataList=lists:map(fun(N)->{N,[{trace,{file,filename:join([PrivDir,
+ "testfile1."++
+ atom_to_list(N)
+ ])}}]} end,
+ Nodes),
+ start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok}]}),
+
+ %% Put some output in the logs.
+ ?l inviso:tp(Nodes,math,module_info,0,[]),
+ ?l inviso:tf(Nodes,all,[call]),
+ ?l lists:foreach(fun(N)->rpc:call(N,math,module_info,[]) end,Nodes),
+
+ stop_tracing(Nodes),
+ {H,M,S}=time(),
+ FetchToDir=filename:join([PrivDir,
+ "fetch_log_test1_"++integer_to_list(H)++"_"++
+ integer_to_list(M)++"_"++integer_to_list(S)]),
+ ?l ok=file:make_dir(FetchToDir),
+ ?l {ok,NodeResults}=inviso:fetch_log(RemoteNodes,FetchToDir,"p1"),
+ io:format("~p~n",[NodeResults]),
+ ?l true=check_noderesults(RemoteNodes,
+ fun({N,{complete,[{trace_log,[{ok,File}]},{ti_log,[]}]}}) ->
+ ?l File="p1testfile1."++atom_to_list(N),
+ true;
+ (_)->
+ false
+ end,
+ NodeResults),
+ ?l ON=filename:join(PrivDir,"testfile1."),
+ ?l FN=filename:join(FetchToDir,"p1testfile1."),
+ ?l lists:foreach(fun(N)->
+ {ok,#file_info{size=Size}}=
+ file:read_file_info(ON++atom_to_list(N)),
+ {ok,#file_info{size=Size}}=
+ file:read_file_info(FN++atom_to_list(N))
+ end,
+ RemoteNodes),
+ %% Now we wish to see that we get an incomplete if we try to fetch to a
+ %% directory that does not exist.
+ ?l FetchToErrorDir=filename:join([PrivDir,nonexistingingdir]),
+ ?l {ok,NodeResults2}=inviso:fetch_log(RemoteNodes,FetchToErrorDir,"p1"),
+ ?l io:format("NodeResults2:~w~n",[NodeResults2]),
+ ?l true=check_noderesults(RemoteNodes,
+ fun({_,{incomplete,_}}) ->
+ true;
+ (_)->
+ false
+ end,
+ NodeResults2),
+ stop(Nodes),
+ ok.
+%% -----------------------------------------------------------------------------
+
+fetch_log_dist_trace_2(suite) -> [];
+fetch_log_dist_trace_2(doc) ->
+ [""];
+fetch_log_dist_trace_2(Config) ->
+ RemoteNodes=get_remotenodes_config(Config),
+ Nodes=[node()|RemoteNodes],
+ PrivDir=filename:join(?config(priv_dir,Config),""),
+
+ {H,M,S}=time(),
+ ?l Name="wrap"++integer_to_list(H)++"_"++integer_to_list(M)++"_"++integer_to_list(S),
+ ?l BaseName=filename:join(PrivDir,Name),
+ Fun=fun(N)->{N,[{trace,{file,{BaseName++atom_to_list(N),wrap,".log",512,2}}},
+ {ti,{file,BaseName++"_ti_"++atom_to_list(N)++".ti"}}]}
+ end,
+ ?l TracerDataList=lists:map(Fun,Nodes),
+ start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}),
+ fill_and_reach_two_wrapfiles(PrivDir,"^"++Name,Nodes),
+
+ stop_tracing(Nodes),
+ FetchToDir=filename:join([PrivDir,
+ "fetch_log_test2_"++integer_to_list(H)++"_"++
+ integer_to_list(M)++"_"++integer_to_list(S)]),
+ ?l ok=file:make_dir(FetchToDir),
+ ?l {ok,NodeResults}=inviso:fetch_log(RemoteNodes,FetchToDir,"p1"),
+ io:format("~p~n",[NodeResults]),
+ CheckFun=fun({N,{complete,[{trace_log,FileResults1},{ti_log,[{ok,TiFile}]}]}}) ->
+ Fun2=fun({ok,File}) ->
+ {match,1,_}=
+ regexp:first_match(File,
+ "^"++"p1"++Name++atom_to_list(N)),
+ true;
+ (_) ->
+ false
+ end,
+ ?l true=lists:all(Fun2,FileResults1),
+ ?l TiFile="p1"++Name++"_ti_"++atom_to_list(N)++".ti",
+ true;
+ (_)->
+ false
+ end,
+ ?l true=check_noderesults(RemoteNodes,CheckFun,NodeResults),
+ stop(Nodes),
+ ok.
+%% -----------------------------------------------------------------------------
+
+fetch_log_dist_trace_3(suite) -> [];
+fetch_log_dist_trace_3(doc) ->
+ [""];
+fetch_log_dist_trace_3(Config) ->
+ RemoteNodes=get_remotenodes_config(Config),
+ Nodes=[node()|RemoteNodes],
+ PrivDir=filename:join(?config(priv_dir,Config),""),
+
+ {H,M,S}=time(),
+ ?l Name="wrap2_"++integer_to_list(H)++"_"++integer_to_list(M)++"_"++integer_to_list(S),
+ ?l BaseName=filename:join(PrivDir,Name),
+ Fun=fun(N)->{N,[{trace,{file,{BaseName++atom_to_list(N),wrap,".log",512,2}}},
+ {ti,{file,BaseName++"_ti_"++atom_to_list(N)++".ti"}}]}
+ end,
+ ?l TracerDataList=lists:map(Fun,Nodes),
+ start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}),
+ fill_and_reach_two_wrapfiles(PrivDir,"^"++Name,Nodes),
+
+ stop_tracing(Nodes),
+ FetchToDir=filename:join([PrivDir,
+ "fetch_log_test3_"++integer_to_list(H)++"_"++
+ integer_to_list(M)++"_"++integer_to_list(S)]),
+ ?l ok=file:make_dir(FetchToDir),
+ ?l {ok,NodeResults1}=inviso:list_logs(Nodes),
+ CheckFun=fun({N,{ok,[{trace_log,PrivDir2,[F1,F2]},{ti_log,PrivDir2,[F3]}]}})->
+ PrivDir2=PrivDir,
+ RegExp="^"++Name++atom_to_list(N)++"[0-9]+"++"\.log",
+ {match,1,_}=regexp:first_match(F1,RegExp),
+ {match,1,_}=regexp:first_match(F2,RegExp),
+ F3=Name++"_ti_"++atom_to_list(N)++".ti",
+ true;
+ (_) ->
+ false
+ end,
+ ?l true=check_noderesults(Nodes,CheckFun,NodeResults1),
+ ?l NodeFileSpecList=lists:map(fun({N,{ok,L}})->{N,L} end,
+ lists:keydelete(node(),1,NodeResults1)),
+ ?l {ok,NodeResults2}=inviso:fetch_log(NodeFileSpecList,FetchToDir,"p1"),
+io:format("~p~n",[NodeResults2]),
+ CheckFun2=fun({N,{complete,[{trace_log,FileResults1},{ti_log,[{ok,TiFile}]}]}}) ->
+ Fun2=fun({ok,File}) ->
+ {match,1,_}=
+ regexp:first_match(File,
+ "^"++"p1"++Name++atom_to_list(N)),
+ true;
+ (_) ->
+ false
+ end,
+ ?l true=lists:all(Fun2,FileResults1),
+ ?l TiFile="p1"++Name++"_ti_"++atom_to_list(N)++".ti",
+ true;
+ (_)->
+ false
+ end,
+ ?l true=check_noderesults(RemoteNodes,CheckFun2,NodeResults2),
+ stop(Nodes),
+ ok.
+%% -----------------------------------------------------------------------------
+
+fetch_log_dist_error_1(suite) -> [];
+fetch_log_dist_error_1(doc) ->
+ [""];
+fetch_log_dist_error_1(Config) when is_list(Config) ->
+ RemoteNodes=get_remotenodes_config(Config),
+ Nodes=[node()|RemoteNodes],
+ ?l {ok,_Pid}=inviso:start(), % Start a control component.
+ ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref),
+ ?l true=check_noderesults(Nodes,{ok,new},NodeResults1),
+ ?l {ok,NodeResults2}=inviso:fetch_log(RemoteNodes,"foo","bar"),
+io:format("~p~n",[NodeResults2]),
+ ?l true=check_noderesults(RemoteNodes,
+ fun({_N,{error,no_tracerdata}})->true;
+ (_)->false
+ end,
+ NodeResults2),
+ stop(Nodes),
+ ok.
+%% -----------------------------------------------------------------------------
+
+fetch_log_dist_error_2(suite) -> [];
+fetch_log_dist_error_2(doc) ->
+ [""];
+fetch_log_dist_error_2(Config) when is_list(Config) ->
+ RemoteNodes=get_remotenodes_config(Config),
+ Nodes=[node()|RemoteNodes],
+ PrivDir=filename:join(?config(priv_dir,Config),""),
+ ?l {ok,_Pid}=inviso:start(), % Start a control component.
+ ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref),
+ ?l true=check_noderesults(Nodes,{ok,new},NodeResults1),
+ ?l NodeLogList=lists:map(fun(N)->{N,[{trace_log,
+ PrivDir,
+ ["f1,fil","f2.fil"]},
+ {ti_log,
+ PrivDir,
+ ["f.ti"]}]}
+ end,
+ RemoteNodes),
+ ?l {ok,NodeResults2}=inviso:fetch_log(NodeLogList,"foo","bar"),
+ io:format("~p~n",[NodeResults2]),
+ ?l true=check_noderesults(RemoteNodes,
+ fun({_N,{incomplete,_}}) ->
+ true;
+ (_) ->
+ false
+ end,
+ NodeResults2),
+ ?l NodeTracerData=lists:map(fun(N)->{N,
+ [{trace,{file,filename:join(PrivDir,"foo")}},
+ {ti,{file,filename:join(PrivDir,"bar.ti")}}]}
+ end,
+ RemoteNodes),
+ {ok,NodeResults3}=inviso:fetch_log(NodeTracerData,"foo","bar"),
+ io:format("~p~n",[NodeResults3]),
+%% This should work this way. Now it says complete [], which is not entirely
+%% incorrect. But to follow the sematics of when fetching named files should
+%% say incomplete.
+%% Must do some rework to make that work. No real danger leaving it this way
+%% for now.
+% ?l true=check_noderesults(RemoteNodes,
+% fun({_N,{incomplete,_}}) ->
+% true;
+% (_) ->
+% false
+% end,
+% NodeResults3),
+ stop(Nodes),
+ ok.
+%% -----------------------------------------------------------------------------
+
+%% TEST CASE: This case tests that the log file merger merges files in the
+%% correct order, based on the timestamps.
+lfm_trace_dist_1(suite) -> [];
+lfm_trace_dist_1(doc) ->
+ [""];
+lfm_trace_dist_1(Config) when is_list(Config) ->
+ RemoteNodes=get_remotenodes_config(Config),
+ Nodes=[node()|RemoteNodes],
+ [RNode1,RNode2|_]=RemoteNodes,
+ PrivDir=filename:join(?config(priv_dir,Config),""),
+ TracerDataList=
+ lists:map(fun(N)->{N,{file,filename:join([PrivDir,"lfm1_"++atom_to_list(N)])}} end,
+ Nodes),
+ start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok}]}),
+ activate_local_tracing(Nodes),
+ activate_traceflags(Nodes),
+
+ {inviso_test_proc,RNode2} ! {apply,code,which,[lists]},
+ timer:sleep(300),
+ {inviso_test_proc,RNode1} ! {apply,code,which,[lists]},
+ timer:sleep(300),
+ {inviso_test_proc,RNode1} ! {apply,code,which,[lists]},
+ timer:sleep(300),
+ inviso_test_proc ! {apply,code,which,[lists]},
+ timer:sleep(300),
+ {inviso_test_proc,RNode2} ! {apply,code,which,[lists]},
+ timer:sleep(300),
+ inviso_test_proc ! {apply,code,which,[lists]},
+
+ deactivate_traceflags(Nodes),
+ deactivate_local_tracing(Nodes),
+ stop_tracing(Nodes),
+ stop(Nodes),
+
+ DestFile=filename:join(PrivDir,"lfm1_out.txt"),
+ ?l {ok,6}=
+ inviso_lfm:merge([{node(),
+ [{trace_log,
+ [filename:join(PrivDir,"lfm1_"++atom_to_list(node()))]}]},
+ {RNode1,
+ [{trace_log,
+ [filename:join(PrivDir,"lfm1_"++atom_to_list(RNode1))]}]},
+ {RNode2,
+ [{trace_log,
+ [filename:join(PrivDir,"lfm1_"++atom_to_list(RNode2))]}]}],
+ DestFile),
+ ?l {ok,FD}=file:open(DestFile,[read]),
+ ?l S1=io:get_line(FD,""),
+ ?l true=lists:prefix(atom_to_list(RNode2),S1),
+ ?l S2=io:get_line(FD,""),
+ ?l true=lists:prefix(atom_to_list(RNode1),S2),
+ ?l S3=io:get_line(FD,""),
+ ?l true=lists:prefix(atom_to_list(RNode1),S3),
+ ?l S4=io:get_line(FD,""),
+ ?l true=lists:prefix(atom_to_list(node()),S4),
+ ?l S5=io:get_line(FD,""),
+ ?l true=lists:prefix(atom_to_list(RNode2),S5),
+ ?l S6=io:get_line(FD,""),
+ ?l true=lists:prefix(atom_to_list(node()),S6),
+ ?l file:close(FD),
+ ok.
+%% -----------------------------------------------------------------------------
+
+%% TEST CASE: Testing to the full extent that pid-mappings work with both
+%% local and global registration. Also checks that pidmappings can be removed
+%% and that consequently the mappings in the resulting merged file stops.
+lfm_trace_ti_dist_2(suite) -> [];
+lfm_trace_ti_dist_2(doc) ->
+ [""];
+lfm_trace_ti_dist_2(Config) when is_list(Config) ->
+ RemoteNodes=get_remotenodes_config(Config),
+ Nodes=[node()|RemoteNodes],
+ [RNode1,RNode2|_]=RemoteNodes,
+ PrivDir=filename:join(?config(priv_dir,Config),""),
+ TracerDataList=
+ lists:map(fun(N)->{N,[{trace,{file,filename:join(PrivDir,"lfm2_"++atom_to_list(N))}},
+ {ti,{file,filename:join(PrivDir,"lfm2_ti_"++atom_to_list(N))}}]}
+ end,
+ Nodes),
+ start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}),
+ activate_local_tracing(Nodes),
+ activate_meta_tracing(Nodes),
+ activate_traceflags(Nodes),
+
+ {inviso_test_proc,RNode2} ! {apply,code,which,[lists]},
+ timer:sleep(300),
+ {inviso_test_proc,RNode1} ! {apply,code,which,[lists]},
+ timer:sleep(300),
+ {inviso_test_proc,RNode1} ! {apply,code,which,[lists]},
+ timer:sleep(300),
+ inviso_test_proc ! {apply,code,which,[lists]},
+ timer:sleep(300),
+
+ P2=spawn(RNode2,?MODULE,test_proc_loop,[]),
+ P1=spawn(RNode1,?MODULE,test_proc_loop,[]),
+ P0=spawn_link(?MODULE,test_proc_loop,[]),
+ ThisNode=node(),
+ ?l {ok,[{ThisNode,{ok,[1]}}]}=inviso:tf([node()],P0,[call,timestamp]),
+ ?l {ok,[{RNode1,{ok,[1]}}]}=inviso:tf([RNode1],P1,[call,timestamp]),
+ ?l {ok,[{RNode2,{ok,[1]}}]}=inviso:tf([RNode2],P2,[call,timestamp]),
+ P2 ! {apply,code,which,[lists]},
+ timer:sleep(300),
+ P1 ! {apply,code,which,[lists]},
+ timer:sleep(300),
+ P0 ! {apply,code,which,[lists]},
+ timer:sleep(300),
+
+ P3=spawn(RNode2,?MODULE,test_proc_loop,[]),
+ ?l yes=global:register_name(inviso_test_proc_globalname,P3),
+ ?l {ok,[{RNode2,{ok,[1]}}]}=inviso:tf([RNode2],P3,[call,timestamp]),
+ timer:sleep(300),
+ P3 ! {apply,code,which,[lists]},
+ timer:sleep(300),
+
+ P4=rpc:call(RNode1,erlang,whereis,[inviso_test_proc]),
+ ?l true=rpc:call(RNode1,erlang,unregister,[inviso_test_proc]),
+ timer:sleep(300),
+ P4 ! {apply,code,which,[lists]},
+ timer:sleep(300),
+
+ ?l true=rpc:call(RNode1,erlang,register,[inviso_test_proc,P4]),
+
+ ?l global:unregister_name(inviso_test_proc_globalname),
+ timer:sleep(300),
+ ?l P3 ! {apply,code,which,[lists]},
+ timer:sleep(300),
+
+ deactivate_traceflags(Nodes),
+ deactivate_local_tracing(Nodes),
+ stop_tracing(Nodes),
+ stop(Nodes),
+
+ DestFile=filename:join(PrivDir,"lfm2_out.txt"),
+ ?l {ok,10}=
+ inviso_lfm:merge([
+ {node(),
+ [{trace_log,
+ [filename:join(PrivDir,"lfm2_"++atom_to_list(node()))]},
+ {ti_log,
+ [filename:join(PrivDir,"lfm2_ti_"++atom_to_list(node()))]}]},
+ {RNode1,
+ [{trace_log,
+ [filename:join(PrivDir,"lfm2_"++atom_to_list(RNode1))]},
+ {ti_log,
+ [filename:join(PrivDir,"lfm2_ti_"++atom_to_list(RNode1))]}]},
+ {RNode2,
+ [{trace_log,
+ [filename:join(PrivDir,"lfm2_"++atom_to_list(RNode2))]},
+ {ti_log,
+ [filename:join(PrivDir,"lfm2_ti_"++atom_to_list(RNode2))]}]}
+ ],
+ DestFile),
+ ?l {ok,FD}=file:open(DestFile,[read]),
+ ?l S1=io:get_line(FD,""),
+io:format("S1 is:~p~n",[S1]),
+ ?l true=lists:prefix(atom_to_list(RNode2)++" [inviso_test_proc",S1),
+ ?l S2=io:get_line(FD,""),
+ ?l true=lists:prefix(atom_to_list(RNode1)++" [inviso_test_proc",S2),
+ ?l S3=io:get_line(FD,""),
+ ?l true=lists:prefix(atom_to_list(RNode1)++" [inviso_test_proc",S3),
+ ?l S4=io:get_line(FD,""),
+ ?l true=lists:prefix(atom_to_list(node())++" [inviso_test_proc",S4),
+ ?l S5=io:get_line(FD,""),
+ ?l true=lists:prefix(atom_to_list(RNode2)++" []",S5),
+ ?l S6=io:get_line(FD,""),
+ ?l true=lists:prefix(atom_to_list(RNode1)++" []",S6),
+ ?l S7=io:get_line(FD,""),
+ ?l true=lists:prefix(atom_to_list(node())++" []",S7),
+ ?l S8=io:get_line(FD,""),
+ ?l true=lists:prefix(atom_to_list(RNode2)++" [{global,inviso_test_proc_globalname}]",S8),
+ ?l S9=io:get_line(FD,""),
+ ?l true=lists:prefix(atom_to_list(RNode1)++" []",S9),
+ ?l S10=io:get_line(FD,""),
+ ?l true=lists:prefix(atom_to_list(RNode2)++" []",S10),
+ ?l file:close(FD),
+ ok.
+%% -----------------------------------------------------------------------------
+
+%% TEST CASE: This tests that the wrapset sorter works.
+handle_logfile_sort_wrapset(suite) -> [];
+handle_logfile_sort_wrapset(doc) ->
+ [""];
+handle_logfile_sort_wrapset(Config) when is_list(Config) ->
+ File0="prefix10.fil",
+ File1="prefix11.fil",
+ File2="prefix12.fil",
+ File3="prefix13.fil",
+ ?l [File0,File1,File2,File3]=
+ inviso_lfm_tpfreader:handle_logfile_sort_wrapset([File2,File1,File0,File3]),
+ File5="prefix15.fil",
+ ?l [File5,File0,File1,File2,File3]=
+ inviso_lfm_tpfreader:handle_logfile_sort_wrapset([File2,File5,File1,File0,File3]),
+ ok.
+%% -----------------------------------------------------------------------------
+
+%% TEST CASE: This case tests that the regexp mechanism in the inviso_rt_lib can
+%% find modules using regexps and that its only_loaded mechanism works.
+%% This test case can not be run when using cover because cover will make the
+%% modules no longer loaded from the path containing "runtime_tools".
+expand_regexp_dist_1(suite) -> [];
+expand_regexp_dist_1(doc) ->
+ [""];
+expand_regexp_dist_1(Config) when is_list(Config) ->
+ case ?t:is_cover() of
+ true ->
+ {skip,"Cover is running"};
+ false ->
+ expand_regexp_dist_1_nocover(Config)
+ end.
+
+expand_regexp_dist_1_nocover(Config) ->
+ RemoteNodes=get_remotenodes_config(Config),
+ Nodes=[node()|RemoteNodes],
+ [RNode1|_]=RemoteNodes,
+ ?l NodeResults1=inviso_rt_lib:expand_regexp(Nodes,"^inviso_rt.*",[]),
+ ?l L1=length(Nodes),
+ ?l L1=length(NodeResults1),
+ ?l true=lists:all(fun({_,Mods})->
+ ?l 3=length(Mods),
+ ?l true=lists:member(inviso_rt,Mods),
+ ?l true=lists:member(inviso_rt_lib,Mods),
+ ?l true=lists:member(inviso_rt_meta,Mods),
+ true;
+ (_) ->
+ false
+ end,
+ NodeResults1),
+ %% Check the dir-option. In the following inviso_tool_lib shall not be found.
+ ?l NodeResults2=inviso_rt_lib:expand_regexp(Nodes,"runtime_tools","invi.*lib.*",[]),
+?l io:format("NodeResults2:~w~n",[NodeResults2]),
+ ?l L1=length(NodeResults2), % Same number of nodes replying.
+ ?l true=lists:all(fun({_,Mods})->
+ 2=length(Mods),
+ true=lists:member(inviso_as_lib,Mods),
+ true=lists:member(inviso_rt_lib,Mods),
+ true;
+ (_) ->
+ false
+ end,
+ NodeResults2),
+ ?l [{RNode1,[]}]=
+ inviso_rt_lib:expand_regexp([RNode1],"^inviso_testmodule1.*",[only_loaded]),
+ ?l [{RNode1,[inviso_testmodule1_foo]}]=
+ inviso_rt_lib:expand_regexp([RNode1],"^inviso_testmodule1.*",[]),
+ ok.
+%% -----------------------------------------------------------------------------
+
+
+only_loaded_dist_1(suite) -> [];
+only_loaded_dist_1(doc) ->
+ [""];
+only_loaded_dist_1(Config) when is_list(Config) ->
+ RemoteNodes=get_remotenodes_config(Config),
+ Nodes=[node()|RemoteNodes],
+ [RNode1|_]=RemoteNodes,
+ PrivDir=filename:join(?config(priv_dir,Config),""),
+ TracerDataList=
+ lists:map(fun(N)->{N,[{trace,{file,filename:join(PrivDir,"ol_1_"++atom_to_list(N))}}]}
+ end,
+ Nodes),
+ start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok}]}),
+ ?l false=rpc:call(RNode1,erlang,module_loaded,[inviso_testmodule1_foo]),
+ ?l {ok,[{RNode1,{ok,[0]}}]}=
+ inviso:tpl([RNode1],inviso_testmodule1_foo,'_','_',[],[only_loaded]),
+ ?l false=rpc:call(RNode1,erlang,module_loaded,[inviso_testmodule1_foo]),
+ ?l {ok,[{RNode1,{ok,[3]}}]}=
+ inviso:tpl([RNode1],inviso_testmodule1_foo,'_','_',[],[]),
+ stop_tracing(Nodes),
+ stop(Nodes),
+ ok.
+
+
+%% ==============================================================================
+%% Common functions setting up inviso.
+%% ==============================================================================
+
+%% Starts controlcomponent and adds runtime components on the nodes specified.
+%% Also initiates tracing on the nodes.
+start_and_init_tracing1(Nodes,Options,TracerData,Reply) when is_list(Nodes) ->
+ ?l {ok,_Pid}=inviso:start(), % Start a control component.
+ ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref,Options),
+ io:format("~p~n",[NodeResults1]),
+ ?l true=check_noderesults(Nodes,{ok,new},NodeResults1),
+ ?l {ok,NodeResults2}=inviso:get_status(Nodes),
+ ?l true=check_noderesults(Nodes,{ok,{new,running}},NodeResults2),
+ ?l {ok,NodeResults3}=inviso:init_tracing(Nodes,TracerData),
+ ?l true=check_noderesults(Nodes,Reply,NodeResults3),
+ ok.
+start_and_init_tracing2(Nodes,Options,TracerDataList,Reply) ->
+ ?l {ok,_Pid}=inviso:start(), % Start a control component.
+ ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref,Options),
+ io:format("~p~n",[NodeResults1]),
+ ?l true=check_noderesults(Nodes,{ok,new},NodeResults1),
+ ?l {ok,NodeResults2}=inviso:get_status(Nodes),
+ ?l true=check_noderesults(Nodes,{ok,{new,running}},NodeResults2),
+ ?l {ok,NodeResults4}=inviso:get_tracerdata(Nodes),
+ ?l true=check_noderesults(Nodes,{ok,no_tracerdata},NodeResults4),
+ ?l {ok,NodeResults3}=inviso:init_tracing(TracerDataList),
+ io:format("Tracerdatalist:~p~n",[TracerDataList]),
+ ?l true=check_noderesults(Nodes,Reply,NodeResults3),
+
+ ?l Fun1=fun({N,{ok,TD}}) when is_list(TD)->
+ ?l {value,{trace,Trace}}=lists:keysearch(trace,1,TD),
+ ?l {value,{N,TD2}}=lists:keysearch(N,1,TracerDataList),
+ ?l true=lists:member({trace,Trace},TD2),
+ %% Check that the trace file really exists.
+ ?l case Trace of % Trace={file,FilePortParameters}
+ {file,FileName1} when is_list(FileName1) ->
+ ?l {ok,_}=rpc:call(N,file,read_file_info,[FileName1]);
+ _ -> % This should be extended with more cases.
+ true
+ end,
+ ?l case lists:keysearch(ti,1,TD2) of
+ {value,{_,Ti}} -> % Ok, we have ti too.
+ ?l {value,{_,Ti}}=lists:keysearch(ti,1,TD),
+ ?l FileName2=element(2,Ti),
+ ?l {ok,_}=rpc:call(N,file,read_file_info,[FileName2]),
+ true;
+ false -> % No ti, we are done now.
+ true
+ end;
+ ({N,{ok,{file,FileName}}}) ->
+ ?l {value,{N,{file,FileName}}}=lists:keysearch(N,1,TracerDataList),
+ ?l {ok,_}=rpc:call(N,file,read_file_info,[FileName]),
+ true;
+ ({N,{ok,LogTD}}) -> % The case using a fun.
+ ?l {value,{N,LogTD}}=lists:keysearch(N,1,TracerDataList),
+ true
+ end,
+ ?l {ok,NodeResults5}=inviso:get_tracerdata(Nodes),
+ ?l true=check_noderesults(Nodes,Fun1,NodeResults5),
+ ok.
+%% ------------------------------------------------------------------------------
+
+%% Stops tracing on Nodes.
+stop_tracing(Nodes) when is_list(Nodes) ->
+ ?l {ok,NodeResults1}=inviso:stop_tracing(Nodes),
+ ?l true=check_noderesults(Nodes,{ok,idle},NodeResults1),
+ ?l {ok,NodeResults2}=inviso:get_status(Nodes),
+ ?l true=check_noderesults(Nodes,{ok,{idle,running}},NodeResults2),
+ %% The implementation says that the meta tracer shall be stopped when
+ %% tracing is stopped. Check that.
+ ?l lists:foreach(fun(N)->
+ ok=poll(erlang,whereis,[inviso_rt_meta],undefined,20)
+ end,
+ Nodes).
+%% ------------------------------------------------------------------------------
+
+%% Stops the runtime components on Nodes and stops the control component at this
+%% Erlang node.
+stop(Nodes) when is_list(Nodes) ->
+ ?l true=check_on_nodes(Nodes,erlang,whereis,[inviso_rt],fun(P) when is_pid(P)->true end),
+ ?l {ok,NodeResults}=inviso:stop_nodes(Nodes),
+ ?l true=check_noderesults(Nodes,ok,NodeResults),
+ ?l true=check_on_nodes(Nodes,erlang,whereis,[inviso_rt],fun(undefined)->true end),
+ ?l true=is_pid(whereis(inviso_c)),
+ ?l shutdown=inviso:stop(),
+ ?l ok=poll(erlang,whereis,[inviso_c],undefined,20).
+%% ------------------------------------------------------------------------------
+
+%% Help function activating local tracing.
+activate_local_tracing(Nodes) when is_list(Nodes) ->
+ ?l true=check_on_nodes(Nodes,
+ erlang,
+ trace_info,
+ [{code,which,1},traced],
+ {traced,false}),
+ ?l {ok,NodeResults}=inviso:tpl(Nodes,code,which,1,[]),
+ ?l true=check_noderesults(Nodes,fun({_,{ok,[1]}})->true end,NodeResults),
+ ?l true=check_on_nodes(Nodes,
+ erlang,
+ trace_info,
+ [{code,which,1},traced],
+ {traced,local}).
+%% ------------------------------------------------------------------------------
+
+%% Help function activating global tracing.
+activate_global_tracing(Nodes) when is_list(Nodes) ->
+ ?l true=check_on_nodes(Nodes,
+ erlang,
+ trace_info,
+ [{code,get_path,0},traced],
+ {traced,false}),
+ ?l {ok,NodeResults}=inviso:tp(Nodes,code,get_path,0,[]),
+ ?l true=check_noderesults(Nodes,fun({_,{ok,[1]}})->true end,NodeResults),
+ ?l true=check_on_nodes(Nodes,
+ erlang,
+ trace_info,
+ [{code,get_path,0},traced],
+ {traced,global}).
+%% ------------------------------------------------------------------------------
+
+
+%% Help function activating local tracing and using a regexp to point out modules.
+%% Returns the structure of modules and functions that were activated. Must be used
+%% when deactivating.
+activate_global_tracing_regexp(Nodes) when is_list(Nodes) ->
+ %% First find out which modules will be effected.
+ ?l Mods1=inviso_rt_lib:expand_regexp("application.*",[]),
+ ?l true=(length(Mods1)>1), % Should find more than one module!
+ ?l Funcs1=lists:foldl(fun(M,Acc)->[{M,M:module_info(exports)}|Acc] end,[],Mods1),
+ %% Check that these functions are not traced.
+ io:format("Modules:~w~n",[Mods1]),
+ ?l {ok,NodeResults}=inviso:tp(Nodes,"application.*",'_','_',[],[]),
+ io:format("Here 2~w~n",[NodeResults]),
+ ?l N=lists:foldl(fun({_,L1},A1)->lists:foldl(fun(_,A2)->A2+1 end,A1,L1) end,0,Funcs1),
+ ?l true=check_noderesults(Nodes,fun({_,{ok,L}})-> N==lists:sum(L) end,NodeResults),
+ io:format("Here 3~n",[]),
+ %% Check again!
+ ?l lists:foreach(fun({M,Funcs})->
+ lists:foreach(fun({F,Arity})->
+ true=check_on_nodes(Nodes,
+ erlang,
+ trace_info,
+ [{M,F,Arity},traced],
+ {traced,global})
+ end,
+ Funcs)
+ end,
+ Funcs1),
+ Funcs1.
+%% ------------------------------------------------------------------------------
+
+%% Help function as above but uses the dir feature as well.
+activate_global_tracing_regexp_dir(Nodes) when is_list(Nodes) ->
+ %% First find out which modules will be effected.
+ ?l Mods1=inviso_rt_lib:expand_regexp(".*kernel.*","application.*",[]),
+ ?l true=(length(Mods1)>1), % Should find more than one module!
+ ?l Funcs1=lists:foldl(fun(M,Acc)->[{M,M:module_info(exports)}|Acc] end,[],Mods1),
+ %% Check that these functions are not traced.
+ io:format("Modules:~w~n",[Mods1]),
+ ?l {ok,NodeResults}=inviso:tp(Nodes,{".*kernel.*","application.*"},'_','_',[],[]),
+ io:format("Here 2~w~n",[NodeResults]),
+ ?l N=lists:foldl(fun({_,L1},A1)->lists:foldl(fun(_,A2)->A2+1 end,A1,L1) end,0,Funcs1),
+ ?l true=check_noderesults(Nodes,fun({_,{ok,L}})-> N==lists:sum(L) end,NodeResults),
+ io:format("Here 3~n",[]),
+ %% Check again!
+ ?l lists:foreach(fun({M,Funcs})->
+ lists:foreach(fun({F,Arity})->
+ true=check_on_nodes(Nodes,
+ erlang,
+ trace_info,
+ [{M,F,Arity},traced],
+ {traced,global})
+ end,
+ Funcs)
+ end,
+ Funcs1),
+ Funcs1.
+%% ------------------------------------------------------------------------------
+
+deactivate_local_tracing(Nodes) when is_list(Nodes) ->
+ ?l true=check_on_nodes(Nodes,
+ erlang,
+ trace_info,
+ [{code,which,1},traced],
+ {traced,local}),
+ ?l {ok,NodeResults}=inviso:ctpl(Nodes,code,'_','_'),
+ ?l true=check_noderesults(Nodes,fun({_,{ok,[N]}})when is_integer(N)->true end,NodeResults),
+ ?l true=check_on_nodes(Nodes,
+ erlang,
+ trace_info,
+ [{code,which,1},traced],
+ {traced,false}).
+%% ------------------------------------------------------------------------------
+
+deactivate_global_tracing(Nodes) when is_list(Nodes) ->
+ ?l true=check_on_nodes(Nodes,
+ erlang,
+ trace_info,
+ [{code,get_path,0},traced],
+ {traced,global}),
+ ?l {ok,NodeResults}=inviso:ctp(Nodes,code,'_','_'),
+ ?l true=check_noderesults(Nodes,fun({_,{ok,[N]}})when is_integer(N)->true end,NodeResults),
+ ?l true=check_on_nodes(Nodes,
+ erlang,
+ trace_info,
+ [{code,get_path,0},traced],
+ {traced,false}).
+%% ------------------------------------------------------------------------------
+
+
+%% Function deactivating the functions activated by activate_global_tracing_regexp/1.
+deactivate_global_tracing_regexp(Nodes,Funcs1) ->
+ ?l lists:foreach(fun({M,Funcs})->
+ lists:foreach(fun({F,Arity})->
+ true=check_on_nodes(Nodes,
+ erlang,
+ trace_info,
+ [{M,F,Arity},traced],
+ {traced,global})
+ end,
+ Funcs)
+ end,
+ Funcs1),
+ ?l {ok,NodeResults}=inviso:ctp(Nodes,"application.*",'_','_'),
+ ?l N=lists:foldl(fun({_,L1},A1)->lists:foldl(fun(_,A2)->A2+1 end,A1,L1) end,0,Funcs1),
+ io:format("Noderesult from deactivate;~w~n",[NodeResults]),
+ ?l true=check_noderesults(Nodes,fun({_,{ok,L}})-> N==lists:sum(L) end,NodeResults),
+ ?l lists:foreach(fun({M,Funcs})->
+ lists:foreach(fun({F,Arity})->
+ true=check_on_nodes(Nodes,
+ erlang,
+ trace_info,
+ [{M,F,Arity},traced],
+ {traced,false})
+ end,
+ Funcs)
+ end,
+ Funcs1).
+%% ------------------------------------------------------------------------------
+
+%% Function deactivating the functions activated by activate_global_tracing_regexp_dir/1.
+deactivate_global_tracing_regexp_dir(Nodes,Funcs1) ->
+ ?l lists:foreach(fun({M,Funcs})->
+ lists:foreach(fun({F,Arity})->
+ true=check_on_nodes(Nodes,
+ erlang,
+ trace_info,
+ [{M,F,Arity},traced],
+ {traced,global})
+ end,
+ Funcs)
+ end,
+ Funcs1),
+ ?l {ok,NodeResults}=inviso:ctp(Nodes,{".*kernel.*","application.*"},'_','_'),
+ ?l N=lists:foldl(fun({_,L1},A1)->lists:foldl(fun(_,A2)->A2+1 end,A1,L1) end,0,Funcs1),
+ io:format("Noderesult from deactivate;~w~n",[NodeResults]),
+ ?l true=check_noderesults(Nodes,fun({_,{ok,L}})-> N==lists:sum(L) end,NodeResults),
+ ?l lists:foreach(fun({M,Funcs})->
+ lists:foreach(fun({F,Arity})->
+ true=check_on_nodes(Nodes,
+ erlang,
+ trace_info,
+ [{M,F,Arity},traced],
+ {traced,false})
+ end,
+ Funcs)
+ end,
+ Funcs1).
+%% ------------------------------------------------------------------------------
+
+%% Help function which starts the inviso_test_proc on all nodes and then sets
+%% the call flag on that process.
+activate_traceflags(Nodes) ->
+ ?l lists:foreach(fun(N)->spawn(N,?MODULE,test_proc_init,[]) end,Nodes),
+ ?l lists:foreach(fun(N)->
+ P=rpc:call(N,erlang,whereis,[inviso_test_proc]),
+ {flags,[]}=rpc:call(N,erlang,trace_info,[P,flags])
+ end,
+ Nodes),
+ ?l {ok,NodeResults}=inviso:tf(Nodes,inviso_test_proc,[call,timestamp]),
+ ?l true=check_noderesults(Nodes,{ok,[1]},NodeResults),
+ ?l lists:foreach(fun(N)->
+ P=rpc:call(N,erlang,whereis,[inviso_test_proc]),
+ {flags,Flags}=rpc:call(N,erlang,trace_info,[P,flags]),
+ true=lists:member(call,Flags),
+ true=lists:member(timestamp,Flags)
+ end,
+ Nodes),
+ %% Now try a globally registered process.
+ ?l [ANode|_]=Nodes,
+ ?l GPid=spawn(ANode,?MODULE,global_test_proc_init,[]),
+ ?l ok=poll(global,whereis_name,[global_inviso_test_proc],
+ fun(P) when is_pid(P)->true;(_)->false end,
+ 10),
+ ?l {ok,NodeResults2}=
+ inviso:tf(Nodes,{global,global_inviso_test_proc},[call,timestamp]),
+ ?l true=check_noderesults(Nodes,
+ fun({N,{ok,[1]}}) when N==ANode->true;
+ ({_,{ok,[0]}})->true;
+ (_)->false
+ end,
+ NodeResults2),
+ ?l {flags,Flags2}=rpc:call(ANode,erlang,trace_info,[GPid,flags]),
+ ?l 2=length(Flags2),
+ ?l true=lists:member(call,Flags2),
+ ?l true=lists:member(timestamp,Flags2),
+ true.
+%% ------------------------------------------------------------------------------
+
+deactivate_traceflags(Nodes) ->
+ ?l lists:foreach(fun(N)->
+ P=rpc:call(N,erlang,whereis,[inviso_test_proc]),
+ {flags,Flags}=rpc:call(N,erlang,trace_info,[P,flags]),
+ true=lists:member(call,Flags),
+ true=lists:member(timestamp,Flags)
+ end,
+ Nodes),
+ ?l {ok,NodeResults}=inviso:ctf(Nodes,inviso_test_proc,[call,timestamp]),
+ ?l true=check_noderesults(Nodes,{ok,[1]},NodeResults),
+ ?l lists:foreach(fun(N)->
+ P=rpc:call(N,erlang,whereis,[inviso_test_proc]),
+ {flags,[]}=rpc:call(N,erlang,trace_info,[P,flags])
+ end,
+ Nodes),
+ ?l GPid=global:whereis_name(global_inviso_test_proc),
+ ?l ANode=node(GPid),
+ ?l {flags,Flags2}=rpc:call(ANode,erlang,trace_info,[GPid,flags]),
+ ?l 2=length(Flags2),
+ ?l {ok,NodeResults2}=inviso:ctf(Nodes,{global,global_inviso_test_proc},[call,timestamp]),
+ ?l true=check_noderesults(Nodes,
+ fun({N,{ok,[1]}}) when N==ANode->true;
+ ({_,{ok,[0]}})->true;
+ (_)->false
+ end,
+ NodeResults2).
+%% ------------------------------------------------------------------------------
+
+
+activate_meta_tracing(Nodes) ->
+ ?l {ok,NodeResults1}=inviso:tpm_localnames(),
+ ?l true=check_noderesults(Nodes,{{ok,1},{ok,1}},NodeResults1),
+ ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]),
+ {meta,P}=rpc:call(N,erlang,trace_info,[{erlang,register,2},meta])
+ end,
+ Nodes),
+ ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]),
+ {meta,P}=rpc:call(N,erlang,trace_info,[{erlang,unregister,1},meta])
+ end,
+ Nodes),
+ ?l {ok,NodeResults2}=inviso:tpm_globalnames(),
+ ?l true=check_noderesults(Nodes,{{ok,1},{ok,1}},NodeResults2),
+ ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]),
+ {meta,P}=rpc:call(N,
+ erlang,
+ trace_info,
+ [{global,handle_call,3},meta])
+ end,
+ Nodes),
+ ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]),
+ {meta,P}=rpc:call(N,
+ erlang,
+ trace_info,
+ [{global,delete_global_name,2},meta])
+ end,
+ Nodes),
+
+ ?l lists:foreach(fun(N)->true=rpc:call(N,
+ ets,
+ insert,
+ [inviso_sideeffect_tab,{tpm_init_func1,0}]),
+ true=rpc:call(N,
+ ets,
+ insert,
+ [inviso_sideeffect_tab,{tpm_call_func1,0}]),
+ true=rpc:call(N,
+ ets,
+ insert,
+ [inviso_sideeffect_tab,{tpm_return_func1,0}])
+ end,
+ Nodes),
+ ?l {ok,NodeResults3}=
+ inviso:init_tpm(lists,
+ module_info,
+ 0,
+ {?MODULE,tpm_init_func1},
+ {?MODULE,tpm_call_func1},
+ {?MODULE,tpm_return_func1},
+ {?MODULE,tpm_remove_func1}),
+ ?l true=check_noderesults(Nodes,ok,NodeResults3),
+ ?l [{_,1}]=ets:lookup(inviso_sideeffect_tab,tpm_init_func1),
+ ?l {ok,NodeResults3a}=
+ inviso:init_tpm(lists,
+ module_info,
+ 0,
+ {?MODULE,tpm_init_func1},
+ {?MODULE,tpm_call_func1},
+ {?MODULE,tpm_return_func1},
+ {?MODULE,tpm_remove_func1}),
+ ?l true=check_noderesults(Nodes,{error,already_initiated},NodeResults3a),
+% %% Try more forbidden things. Wildcards not allowed in meta tracing!
+% ?l {ok,NodeResults3b}=inviso:tpm(Nodes,lists,'_',0,[{'_',[],[{return_trace}]}]),
+% io:format("The noderesults3b is:~w~n",[NodeResults3b]),
+% ?l true=check_noderesults(Nodes,{error,bad_mfa},NodeResults3b),
+ ?l {ok,NodeResults3c}=inviso:tpm(Nodes,lists,module_info,0,[{'_',[],[{return_trace}]}]),
+ ?l true=check_noderesults(Nodes,{ok,1},NodeResults3c),
+ ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]),
+ {meta,P}=rpc:call(N,erlang,trace_info,[{lists,module_info,0},meta])
+ end,
+ Nodes),
+ ?l lists:foreach(fun(N)->rpc:call(N,lists,module_info,[]) end,Nodes),
+ ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_call_func1],[{tpm_call_func1,1}],20),
+ ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_return_func1],[{tpm_return_func1,1}],20),
+ ?l lists:foreach(fun(N)->rpc:call(N,lists,module_info,[]) end,Nodes),
+ ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_call_func1],[{tpm_call_func1,2}],20),
+ ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_return_func1],[{tpm_return_func1,2}],20),
+
+ ?l {ok,NodeResults4}=
+ inviso:init_tpm(math,
+ module_info,
+ 1,
+ {?MODULE,tpm_init_func2}, % Does not exist on purpose.
+ {?MODULE,tpm_call_func2}, % Does not exist on purpose.
+ {?MODULE,tpm_return_func2}, % Does not exist on purpose.
+ {?MODULE,tpm_remove_func2}), % Does not exist on purpose.
+ ?l true=check_noderesults(Nodes,ok,NodeResults4),
+ ?l {ok,NodeResults5}=
+ inviso:tpm_ms(math,module_info,1,ms1,[{'_',[],[{return_trace}]}]),
+ ?l true=check_noderesults(Nodes,{ok,1},NodeResults5),
+ ?l lists:foreach(fun(N)->{meta_match_spec,[{'_',[],[{return_trace}]}]}=
+ rpc:call(N,erlang,trace_info,[{math,module_info,1},
+ meta_match_spec])
+ end,
+ Nodes),
+
+ ?l {ok,NodeResults6}=inviso:tpm_ms(math,module_info,1,ms2,[{[exports],[],[]}]),
+ ?l true=check_noderesults(Nodes,{ok,1},NodeResults6),
+ ?l lists:foreach(fun(N)->{meta_match_spec,[{[exports],[],[]},{'_',[],[{return_trace}]}]}=
+ rpc:call(N,erlang,trace_info,[{math,module_info,1},
+ meta_match_spec])
+ end,
+ Nodes),
+ ?l {ok,NodeResults7}=inviso:tpm_ms(math,module_info,1,ms3,[{[attributes],[],[]}]),
+ ?l true=check_noderesults(Nodes,{ok,1},NodeResults7),
+ ?l lists:foreach(fun(N)->{meta_match_spec,[{[attributes],[],[]},
+ {[exports],[],[]},
+ {'_',[],[{return_trace}]}]}=
+ rpc:call(N,erlang,trace_info,[{math,module_info,1},
+ meta_match_spec])
+ end,
+ Nodes),
+ ?l {ok,NodeResults8}=inviso:ctpm_ms(math,module_info,1,ms2),
+ ?l true=check_noderesults(Nodes,ok,NodeResults8),
+ ?l lists:foreach(fun(N)->{meta_match_spec,[{[attributes],[],[]},
+ {'_',[],[{return_trace}]}]}=
+ rpc:call(N,erlang,trace_info,[{math,module_info,1},
+ meta_match_spec])
+ end,
+ Nodes),
+ ?l io:format("whereis:~w~n",[lists:map(fun(N)->rpc:call(N,erlang,whereis,[inviso_rt_meta]) end,Nodes)]),
+ ?l {ok,NodeResults8}=inviso:ctpm_ms(math,module_info,1,ms3),
+ ?l io:format("whereis:~w~n",[lists:map(fun(N)->rpc:call(N,erlang,whereis,[inviso_rt_meta]) end,Nodes)]),
+ ?l {ok,NodeResults8}=inviso:ctpm_ms(math,module_info,1,ms1),
+ ?l lists:foreach(fun(N)->{meta_match_spec,false}=
+ rpc:call(N,erlang,trace_info,[{math,module_info,1},
+ meta_match_spec])
+ end,
+ Nodes),
+
+ %% Now try to do this with exception tracing instead.
+ %% Reset the side effect tables.
+ ?l lists:foreach(fun(N)->true=rpc:call(N,
+ ets,
+ insert,
+ [inviso_sideeffect_tab,{tpm_init_func1,0}]),
+ true=rpc:call(N,
+ ets,
+ insert,
+ [inviso_sideeffect_tab,{tpm_call_func1,0}]),
+ true=rpc:call(N,
+ ets,
+ insert,
+ [inviso_sideeffect_tab,{tpm_return_func1,0}])
+ end,
+ Nodes),
+ ?l {ok,NodeResults9}=
+ inviso:init_tpm(?MODULE,
+ failing_function,
+ 1,
+ {?MODULE,tpm_init_func1},
+ {?MODULE,tpm_call_func1},
+ {?MODULE,tpm_return_func1},
+ {?MODULE,tpm_remove_func1}),
+ ?l true=check_noderesults(Nodes,ok,NodeResults9),
+ ?l [{_,1}]=ets:lookup(inviso_sideeffect_tab,tpm_init_func1),
+ ?l {ok,NodeResults10}=inviso:tpm(Nodes,?MODULE,failing_function,1,[{'_',[],[{exception_trace}]}]),
+ ?l true=check_noderesults(Nodes,{ok,1},NodeResults10),
+ ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]),
+ {meta,P}=rpc:call(N,erlang,trace_info,[{?MODULE,failing_function,1},meta])
+ end,
+ Nodes),
+ ?l lists:foreach(fun(N)->rpc:call(N,?MODULE,failing_function,[nofailure]) end,Nodes),
+ ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_call_func1],[{tpm_call_func1,1}],20),
+ ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_return_func1],[{tpm_return_func1,1}],20),
+ ?l lists:foreach(fun(N)->rpc:call(N,?MODULE,failing_function,[failure]) end,Nodes),
+ ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_call_func1],[{tpm_call_func1,2}],20),
+ ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_return_func1],[{tpm_return_func1,3}],20),
+
+ ok.
+%% ------------------------------------------------------------------------------
+
+%% This function is for testing that appending the tracer to a trace action term
+%% works.
+activate_deactivate_meta_tracing_tracer(Nodes) ->
+ ?l {ok,NodeResults}=
+ inviso:tpm_tracer(Nodes,lists,module_info,0,[{'_',[],[{trace,[all],[call]}]}],void),
+ ?l true=check_noderesults(Nodes,{ok,1},NodeResults),
+ ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]),
+ {meta,P}=rpc:call(N,erlang,trace_info,[{lists,module_info,0},meta]),
+ {meta_match_spec,[{'_',[],[{trace,[all],Enable}]}]}=
+ rpc:call(N,erlang,trace_info,[{lists,module_info,0},
+ meta_match_spec]),
+ true=list_search(Enable,fun({{tracer,P}}) when is_port(P)->true;
+ (_) -> false
+ end)
+ end,
+ Nodes),
+ ?l {ok,NodeResults2}=
+ inviso:ctpm(Nodes,lists,module_info,0),
+ ?l true=check_noderesults(Nodes,ok,NodeResults2),
+ ?l lists:foreach(fun(N)->{meta,false}=
+ rpc:call(N,erlang,trace_info,[{lists,module_info,0},meta])
+ end,
+ Nodes),
+ ok.
+%% ------------------------------------------------------------------------------
+
+deactivate_meta_tracing(Nodes) ->
+ ?l lists:foreach(fun(N)->{meta,P}=
+ rpc:call(N,erlang,trace_info,[{erlang,register,2},meta]),
+ true=is_pid(P)
+ end,
+ Nodes),
+ ?l lists:foreach(fun(N)->{meta,P}=
+ rpc:call(N,erlang,trace_info,[{erlang,unregister,1},meta]),
+ true=is_pid(P)
+ end,
+ Nodes),
+ ?l {ok,NodeResults1}=inviso:ctpm_localnames(),
+ ?l lists:foreach(fun(N)->{meta,false}=
+ rpc:call(N,erlang,trace_info,[{erlang,register,2},meta]) end,
+ Nodes),
+ ?l lists:foreach(fun(N)->{meta,false}=
+ rpc:call(N,erlang,trace_info,[{erlang,unregister,1},meta])
+ end,
+ Nodes),
+ ?l true=check_noderesults(Nodes,{ok,ok},NodeResults1),
+
+ ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]),
+ {meta,P}=rpc:call(N,
+ erlang,
+ trace_info,
+ [{global,handle_call,3},meta])
+ end,
+ Nodes),
+ ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]),
+ {meta,P}=rpc:call(N,
+ erlang,
+ trace_info,
+ [{global,delete_global_name,2},meta])
+ end,
+ Nodes),
+ ?l {ok,NodeResults1b}=inviso:ctpm_globalnames(),
+ ?l true=check_noderesults(Nodes,{ok,ok},NodeResults1b),
+ ?l lists:foreach(fun(N)->
+ {meta,false}=rpc:call(N,
+ erlang,
+ trace_info,
+ [{global,handle_call,3},meta])
+ end,
+ Nodes),
+ ?l lists:foreach(fun(N)->
+ {meta,false}=rpc:call(N,
+ erlang,
+ trace_info,
+ [{global,delete_global_name,2},meta])
+ end,
+ Nodes),
+
+ ?l lists:foreach(fun(N)->{meta,P}=
+ rpc:call(N,erlang,trace_info,[{lists,module_info,0},meta]),
+ true=is_pid(P)
+ end,
+ Nodes),
+ ?l {ok,NodeResults2}=inviso:ctpm(lists,module_info,0),
+ ?l true=check_noderesults(Nodes,ok,NodeResults2),
+ ?l lists:foreach(fun(N)->{meta,false}=
+ rpc:call(N,erlang,trace_info,[{lists,module_info,0},meta]) end,
+ Nodes),
+ ?l [{_,0}]=ets:lookup(inviso_sideeffect_tab,tpm_init_func1),
+ ?l {ok,NodeResults3}=inviso:ctpm(math,module_info,1),
+ ?l true=check_noderesults(Nodes,ok,NodeResults3),
+ ok.
+%% ------------------------------------------------------------------------------
+
+%% Functions acting as callbacks for testing the meta tracing mechanisms.
+tpm_init_func1(_M,_F,_Arity,PublLD) ->
+ ets:update_counter(inviso_sideeffect_tab,tpm_init_func1,1),
+ {ok,PublLD,void}.
+tpm_call_func1(_Pid,{call,_Args,_TS},PublLD) ->
+ ets:update_counter(inviso_sideeffect_tab,tpm_call_func1,1),
+ {ok,PublLD,void}.
+tpm_return_func1(_Pid,{return_from,_ReturnVal,_TS},PublLD) ->
+ ets:update_counter(inviso_sideeffect_tab,tpm_return_func1,1),
+ {ok,PublLD,void};
+tpm_return_func1(_Pid,{exception_from,_ReturnVal,_TS},PublLD) ->
+ ets:update_counter(inviso_sideeffect_tab,tpm_return_func1,1),
+ ets:update_counter(inviso_sideeffect_tab,tpm_return_func1,1),
+ {ok,PublLD,void}.
+tpm_remove_func1(_M,_F,_Arity,PublLD) ->
+ ets:update_counter(inviso_sideeffect_tab,tpm_init_func1,-1),
+ {ok,PublLD}.
+%% ------------------------------------------------------------------------------
+
+
+%% Help function which traces on a function and makes function calls until there
+%% are two files in the wrap-set.
+fill_and_reach_two_wrapfiles(PrivDir,RegExp,Nodes) ->
+ ?l lists:foreach(fun(N)->spawn(N,?MODULE,test_proc_init,[]) end,Nodes),
+ ?l {ok,NodeResults1}=inviso:tpl(Nodes,?MODULE,test_function,0,[]),
+ ?l true=check_noderesults(Nodes,{ok,[1]},NodeResults1),
+ ?l {ok,NodeResults2}=inviso:tf(Nodes,inviso_test_proc,[call]),
+ ?l true=check_noderesults(Nodes,{ok,[1]},NodeResults2),
+ fill_and_reach_two_wrapfiles_2(PrivDir,RegExp,Nodes),
+ ?l {ok,NodeResults3}=inviso:ctf(Nodes,inviso_test_proc,[call]),
+ ?l true=check_noderesults(Nodes,{ok,[1]},NodeResults3),
+ ?l {ok,NodeResults4}=inviso:ctpl(Nodes,?MODULE,test_function,0),
+ ?l true=check_noderesults(Nodes,{ok,[1]},NodeResults4),
+ ok.
+
+fill_and_reach_two_wrapfiles_2(PrivDir,RegExp,[Node|Rest]) ->
+ ?l ok=rpc:call(Node,?MODULE,fill_and_reach_two_wrapfiles_3,[PrivDir,RegExp]),
+ fill_and_reach_two_wrapfiles_2(PrivDir,RegExp,Rest);
+fill_and_reach_two_wrapfiles_2(_,_,[]) ->
+ ok.
+
+fill_and_reach_two_wrapfiles_3(Dir,RegExp) ->
+ ok=send_to_test_proc({apply,?MODULE,test_function,[]},
+ fun reach_two_wraps_stopfun/1,
+ {Dir,RegExp++atom_to_list(node())},
+ 100).
+
+%% Help function intended to be used as fun in a send_to_test_proc/4 call.
+%% The function lists the content of Dir and looks for occurancies of String.
+%% If two files containing the string String are found, 'done' is returned.
+%% Otherwise 'continue'.
+reach_two_wraps_stopfun({Dir,RegExp}) ->
+ case file:list_dir(Dir) of
+ {ok,FileNames} ->
+ case how_many_files_regexp(FileNames,RegExp,0) of
+ {ok,2} ->
+ done;
+ _ ->
+ continue
+ end;
+ {error,_Reason} ->
+ error
+ end.
+%% ------------------------------------------------------------------------------
+
+%% ------------------------------------------------------------------------------
+%% Help function for the overload tests. These functions are used as callbacks.
+%% ------------------------------------------------------------------------------
+
+overload1(_) ->
+ ets:update_counter(inviso_sideeffect_tab,ovl1,1),
+ ok.
+%% This function is used when timeout occurs inside the runtime component.
+%% That is it is time to check for overload.
+overload2({timeout,overload2i_data}) ->
+ ets:update_counter(inviso_sideeffect_tab,ovl2,1),
+ ok.
+overload2i() ->
+ ets:insert(inviso_sideeffect_tab,{ovl2,0}),
+ {ok,overload2i_data}.
+overload2r(overload2i_data) ->
+ ets:delete(inviso_sideeffect_tab,ovl2).
+
+%% This function is used when timeout occurs inside the runtime component.
+%% That is it is time to check for overload.
+overload3({timeout,overload3i_data}) ->
+ ets:update_counter(inviso_sideeffect_tab,ovl3,1),
+ ok;
+overload3(_) -> % Must handle garbage too.
+ ignore.
+overload3i() ->
+ ets:insert(inviso_sideeffect_tab,{ovl3,0}),
+ {ok,overload3i_data}.
+overload3r(overload3i_data) ->
+ ets:insert(inviso_sideeffect_tab,{ovl3r,done}),
+ ets:delete(inviso_sideeffect_tab,ovl3).
+
+overload4(_) ->
+ case ets:lookup(inviso_sideeffect_tab,ovl4_suspend) of
+ [] -> % We are supposed to be running.
+ ets:update_counter(inviso_sideeffect_tab,ovl4,1),
+ ok;
+ [_] ->
+ {suspend,test}
+ end.
+
+%% This function is used when overload check is done by icomming message.
+overload5({msg,{test_of_loadcheck,overload5i_data}}) ->
+ ets:update_counter(inviso_sideeffect_tab,ovl5,1),
+ ok;
+overload5(_) ->
+ ignore.
+overload5i() ->
+ ets:insert(inviso_sideeffect_tab,{ovl5,0}),
+ {ok,overload5i_data}.
+overload5r(overload5i_data) ->
+ ets:delete(inviso_sideeffect_tab,ovl5),
+ ets:insert(inviso_sideeffect_tab,{ovl5r,done});
+overload5r(X) ->
+ erlang:display({'***',overload5r,X}).
+
+overload6(_) ->
+ ets:update_counter(inviso_sideeffect_tab,ovl6,1),
+ ok.
+%% ------------------------------------------------------------------------------
+
+%% ------------------------------------------------------------------------------
+%% Help function for the subscription tests. These function implements a collector
+%% process which will subscribe to inviso_events from the control component.
+%% ------------------------------------------------------------------------------
+
+%% Function which can be used to check if an inviso_event has arrived. The function
+%% takes a fun which tests the messages.
+check_msg_collector([],_,_) ->
+ true;
+check_msg_collector(_,_,0) ->
+ false;
+check_msg_collector(Nodes,Fun,T) ->
+ Ref=make_ref(),
+ inviso_collector_proc ! {fetch_message,self(),Ref,Fun},
+ receive
+ {inviso,Ref,{true,Node}} ->
+ check_msg_collector(lists:delete(Node,Nodes),Fun,T-1);
+ {inviso,Ref,false} ->
+ timer:sleep(100),
+ check_msg_collector(Nodes,Fun,T-1)
+ end.
+
+%% Spawn on this function to get a subscriber.
+inviso_msg_collector() ->
+ register(inviso_collector_proc,self()),
+ inviso_msg_collector_loop([]).
+
+inviso_msg_collector_loop(Msgs) ->
+ receive
+ {fetch_message,From,Ref,Fun} ->
+ {NewMsgs,Reply}=inviso_msg_collector_selector(Msgs,Fun,[]),
+ From ! {inviso,Ref,Reply},
+ inviso_msg_collector_loop(NewMsgs);
+ Msg ->
+ inviso_msg_collector_loop([Msg|Msgs])
+ end.
+
+inviso_msg_collector_selector([M|Rest],Fun,Accum) ->
+ case Fun(M) of
+ {true,X} ->
+ {Rest++Accum,{true,X}};
+ _ ->
+ inviso_msg_collector_selector(Rest,Fun,[M|Accum])
+ end;
+inviso_msg_collector_selector([],_,Accum) ->
+ {Accum,false}.
+%% ------------------------------------------------------------------------------
+
+
+%% ==============================================================================
+%% Help functions
+%% ==============================================================================
+
+list_search([E|Rest],Fun) ->
+ case Fun(E) of
+ true ->
+ true;
+ false ->
+ list_search(Rest,Fun)
+ end;
+list_search([],_Fun) ->
+ false.
+%% ------------------------------------------------------------------------------
+
+%% Help function checking that there is a Result for each node in Nodes.
+%% Returns 'true' if successful.
+check_noderesults(Nodes,Fun,[{Node,Result}|Rest]) when is_function(Fun) ->
+ case Fun({Node,Result}) of
+ true ->
+ case lists:member(Node,Nodes) of
+ true ->
+ check_noderesults(lists:delete(Node,Nodes),Fun,Rest);
+ false -> % Not good.
+ unknown_node_in_returnvalue
+ end;
+ _ ->
+ illegal_result
+ end;
+check_noderesults(Nodes,Result,[{Node,Result}|Rest]) ->
+ case lists:member(Node,Nodes) of
+ true ->
+ check_noderesults(lists:delete(Node,Nodes),Result,Rest);
+ false -> % Not good.
+ unknown_node_in_returnvalue
+ end;
+check_noderesults([],_,[]) ->
+ true;
+check_noderesults(X,Y,Z) ->
+ io:format("Bad arguments to check noderesults:~w~n~w~n~w~n",[X,Y,Z]),
+ false.
+%% ------------------------------------------------------------------------------
+
+%% Help function doing rpc on all nodes in Nodes calling M:F. Returns 'true' if
+%% successful.
+check_on_nodes([Node|Rest],M,F,Args,Result) when Node==node() ->
+ if
+ is_function(Result) ->
+ ?l true=Result(apply(M,F,Args));
+ true ->
+ ?l Result=apply(M,F,Args)
+ end,
+ check_on_nodes(Rest,M,F,Args,Result);
+check_on_nodes([Node|Rest],M,F,Args,Result) ->
+ if
+ is_function(Result) ->
+ ?l true=Result(rpc:call(Node,M,F,Args));
+ true ->
+ ?l Result=rpc:call(Node,M,F,Args)
+ end,
+ check_on_nodes(Rest,M,F,Args,Result);
+check_on_nodes([],_,_,_,_) ->
+ true.
+%% ------------------------------------------------------------------------------
+
+%% Help function which given a list of files searches through it and returns
+%% how many satisfies the RegExp.
+%% Returns {ok,N}.
+how_many_files_regexp([],_,N) ->
+ {ok,N};
+how_many_files_regexp([FName|Rest],RegExp,N) ->
+ case regexp:first_match(FName,RegExp) of
+ {match,1,_} ->
+ how_many_files_regexp(Rest,RegExp,N+1);
+ nomatch ->
+ how_many_files_regexp(Rest,RegExp,N);
+ {error,Reason} ->
+ test_server:fail(Reason)
+ end.
+%% ------------------------------------------------------------------------------
+
+%% Help function killing a bunch of registered processes.
+process_killer([RegName|Rest]) ->
+ case whereis(RegName) of
+ undefined ->
+ case global:whereis_name(RegName) of
+ undefined ->
+ process_killer(Rest);
+ P when is_pid(P) ->
+ if
+ node()==node(P) ->
+ exit(P,kill);
+ true ->
+ true
+ end,
+ process_killer(Rest)
+ end;
+ P when is_pid(P) ->
+ exit(P,kill),
+ process_killer(Rest)
+ end;
+process_killer([]) ->
+ true.
+%% ------------------------------------------------------------------------------
+
+%% Help function which waits for a function call to become Result. This is useful
+%% if what we are waiting for can happend independantly of indications we have
+%% access to.
+poll(_,_,_,_,0) ->
+ error;
+poll(M,F,Args,Result,Times) ->
+ try apply(M,F,Args) of
+ What when is_function(Result) ->
+ case Result(What) of
+ true ->
+ ok;
+ _ ->
+ timer:sleep(100),
+ poll(M,F,Args,Result,Times-1)
+ end;
+ Result ->
+ ok;
+ _ ->
+ timer:sleep(100),
+ poll(M,F,Args,Result,Times-1)
+ catch
+ error:Reason ->
+ io:format("Apply in suite-function poll/5 failed, ~w~n",[Reason]),
+ timer:sleep(100),
+ poll(M,F,Args,Result,Times-1)
+ end.
+%% ------------------------------------------------------------------------------
+
+insert_remotenode_config(Name,Node,Config) ->
+ [{remotenode,{Name,Node}}|Config].
+%% ------------------------------------------------------------------------------
+
+insert_timetraphandle_config(Handle,Config) ->
+ [{timetraphandle,Handle}|Config].
+%% ------------------------------------------------------------------------------
+
+get_remotenode_config(Name, [{remotenode, {Name, Node}}| _Cs]) ->
+ Node;
+get_remotenode_config(Name, [_ | Cs]) ->
+ get_remotenode_config(Name, Cs);
+get_remotenode_config(Name, []) ->
+ exit({no_remotenode, Name}).
+
+%% ------------------------------------------------------------------------------
+
+get_timetraphandle_config(Config) ->
+ {value,{_,Handle}}=lists:keysearch(timetraphandle,1,Config),
+ Handle.
+%% ------------------------------------------------------------------------------
+
+get_remotenodes_config([{remotenode,{_Name,Node}}|Config]) ->
+ [Node|get_remotenodes_config(Config)];
+get_remotenodes_config([_|Config]) ->
+ get_remotenodes_config(Config);
+get_remotenodes_config([]) ->
+ [].
+%% ------------------------------------------------------------------------------
+
+remove_remotenode_config(Name, [{remotenode, {Name, _}} | Cs]) ->
+ Cs;
+remove_remotenode_config(Name, [C | Cs]) ->
+ [C | remove_remotenode_config(Name, Cs)];
+remove_remotenode_config(_Name, []) ->
+ [].
+
+%% ------------------------------------------------------------------------------
+
+remove_timetraphandle_config(Config) ->
+ lists:keydelete(timetraphandle,1,Config).
+%% ------------------------------------------------------------------------------
+
+%% This function can be meta traced in order to check that exception_trace works.
+%% Must be exported.
+failing_function(nofailure) ->
+ true;
+failing_function(failure) ->
+ exit(failure).
+%% ------------------------------------------------------------------------------
+
+%% ==============================================================================
+%% Code for a test process which can be started.
+%% ==============================================================================
+
+test_proc_init() ->
+ register(inviso_test_proc,self()),
+ test_proc_loop().
+
+test_proc_loop() ->
+ receive
+ {apply,M,F,Args} ->
+ apply(M,F,Args),
+ test_proc_loop();
+ X ->
+ io:format("Got ~w~n",[X]),
+ test_proc_loop()
+ end.
+
+global_test_proc_init() ->
+ global:register_name(global_inviso_test_proc,self()),
+ test_proc_loop().
+%% ------------------------------------------------------------------------------
+
+send_to_test_proc(_,_,_,0) ->
+ error;
+send_to_test_proc(Msg,Fun,FunArg,N) ->
+ inviso_test_proc ! Msg,
+ case Fun(FunArg) of
+ done ->
+ ok;
+ error ->
+ test_server:fail(send_to_test_proc);
+ _ ->
+ send_to_test_proc(Msg,Fun,FunArg,N-1)
+ end.
+%% ------------------------------------------------------------------------------
+
+
+%% This function is here to be traced on by the inviso_test_proc. Must be exported.
+test_function() ->
+ 1+1.
+%% ------------------------------------------------------------------------------
+
+
+%% ==============================================================================
+%% Code for a test side effect table process.
+%% ==============================================================================
+
+%% The side effect logger is a process owning a public ETS table. The idea is that
+%% various callback functions can write in the table when called. In that way
+%% correct calling of the call-backs can be verified.
+start_side_effect_logger(Node) ->
+ ?l true=is_pid(spawn(Node,?MODULE,side_effect_logger_proc,[])),
+ ?l ok=poll(rpc,call,[Node,ets,lookup,[inviso_sideeffect_tab,foo]],[],20).
+
+%% This one must be exported.
+side_effect_logger_proc() ->
+ register(inviso_tab_proc,self()), % So we can kill it later.
+ ets:new(inviso_sideeffect_tab,[public,named_table]),
+ side_effect_logger_proc_2().
+
+side_effect_logger_proc_2() ->
+ receive
+ _X -> % This process is not expecting anything!
+ side_effect_logger_proc_2()
+ end.
+%% ------------------------------------------------------------------------------
diff --git a/lib/runtime_tools/test/inviso_testmodule1_foo.erl b/lib/runtime_tools/test/inviso_testmodule1_foo.erl
new file mode 100644
index 0000000000..a7a22cad39
--- /dev/null
+++ b/lib/runtime_tools/test/inviso_testmodule1_foo.erl
@@ -0,0 +1,9 @@
+-module(inviso_testmodule1_foo).
+
+-compile(export_all).
+
+%% The purpose of this module is simply to have a module that is
+%% guaranteed not loaded.
+
+foo() ->
+ true.
diff --git a/lib/runtime_tools/test/runtime_tools.cover b/lib/runtime_tools/test/runtime_tools.cover
new file mode 100644
index 0000000000..2d62ebe6ac
--- /dev/null
+++ b/lib/runtime_tools/test/runtime_tools.cover
@@ -0,0 +1 @@
+{exclude,[observer_backend]}.
diff --git a/lib/runtime_tools/test/runtime_tools.spec b/lib/runtime_tools/test/runtime_tools.spec
new file mode 100644
index 0000000000..a60a533ce2
--- /dev/null
+++ b/lib/runtime_tools/test/runtime_tools.spec
@@ -0,0 +1 @@
+{topcase, {dir, "../runtime_tools_test"}}.
diff --git a/lib/runtime_tools/test/runtime_tools_SUITE.erl b/lib/runtime_tools/test/runtime_tools_SUITE.erl
new file mode 100644
index 0000000000..84e255e126
--- /dev/null
+++ b/lib/runtime_tools/test/runtime_tools_SUITE.erl
@@ -0,0 +1,50 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(runtime_tools_SUITE).
+-include("test_server.hrl").
+
+%% Test server specific exports
+-export([all/1]).
+-export([init_per_testcase/2, end_per_testcase/2]).
+
+%% Test cases
+-export([app_file/1]).
+
+%% Default timetrap timeout (set in init_per_testcase)
+-define(default_timeout, ?t:minutes(1)).
+
+init_per_testcase(_Case, Config) ->
+ Dog = test_server:timetrap(?default_timeout),
+ [{watchdog, Dog} | Config].
+
+end_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+all(suite) ->
+ [app_file].
+
+app_file(suite) ->
+ [];
+app_file(doc) ->
+ ["Testing .app file"];
+app_file(Config) when is_list(Config) ->
+ ?line ok = ?t:app_test(runtime_tools),
+ ok.
diff --git a/lib/runtime_tools/vsn.mk b/lib/runtime_tools/vsn.mk
index 9e87d5b144..8be4ae613b 100644
--- a/lib/runtime_tools/vsn.mk
+++ b/lib/runtime_tools/vsn.mk
@@ -1 +1 @@
-RUNTIME_TOOLS_VSN = 1.8.4
+RUNTIME_TOOLS_VSN = 1.8.4.1
diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml
index 3f4954cfbd..493e7aa092 100644
--- a/lib/snmp/doc/src/notes.xml
+++ b/lib/snmp/doc/src/notes.xml
@@ -13,12 +13,12 @@
compliance with the License. You should have received a copy of the
Erlang Public License along with this software. If not, it can be
retrieved online at http://www.erlang.org/.
-
+
Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
the License for the specific language governing rights and limitations
under the License.
-
+
</legalnotice>
<title>SNMP Release Notes</title>
@@ -32,6 +32,50 @@
<file>notes.xml</file>
</header>
+ <section><title>SNMP 4.18</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ When the function FilterMod:accept_recv/2 returned false
+ the SNMP agent stopped collecting messages from UDP.</p>
+ <p>
+ Own Id: OTP-8761</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section>
+ <title>SNMP Development Toolkit 4.17.1</title>
+ <p>Version 4.17.1 supports code replacement in runtime from/to
+ version 4.17, 4.16.2, 4.16.1, 4.16, 4.15, 4.14 and 4.13.5.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <p>-</p>
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <list type="bulleted">
+ <item>
+ <p>When the function FilterMod:accept_recv/2
+ returned false the SNMP agent stopped collecting messages from UDP.</p>
+ <p>Own Id: OTP-8761</p>
+ </item>
+ </list>
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.17.1 -->
+
+
<section>
<title>SNMP Development Toolkit 4.17</title>
<p>Version 4.17 supports code replacement in runtime from/to
diff --git a/lib/snmp/examples/ex2/snmp_ex2_manager.erl b/lib/snmp/examples/ex2/snmp_ex2_manager.erl
index 79cfd94469..ff873327bc 100644
--- a/lib/snmp/examples/ex2/snmp_ex2_manager.erl
+++ b/lib/snmp/examples/ex2/snmp_ex2_manager.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -25,6 +25,8 @@
-behaviour(gen_server).
-behaviour(snmpm_user).
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([start_link/0, start_link/1, stop/0,
agent/2,
sync_get/2,
diff --git a/lib/snmp/examples/ex2/snmp_ex2_simple_standard_test.erl b/lib/snmp/examples/ex2/snmp_ex2_simple_standard_test.erl
index 16fe79d1a5..81939dd614 100644
--- a/lib/snmp/examples/ex2/snmp_ex2_simple_standard_test.erl
+++ b/lib/snmp/examples/ex2/snmp_ex2_simple_standard_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -22,6 +22,8 @@
-module(snmp_ex2_simple_standard_test).
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([start/0, start/1, start/3]).
-include_lib("snmp/include/snmp_types.hrl").
diff --git a/lib/snmp/src/agent/snmp_community_mib.erl b/lib/snmp/src/agent/snmp_community_mib.erl
index a2ee7bf0c9..8f0f4cad73 100644
--- a/lib/snmp/src/agent/snmp_community_mib.erl
+++ b/lib/snmp/src/agent/snmp_community_mib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -18,6 +18,8 @@
%%
-module(snmp_community_mib).
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([configure/1, reconfigure/1,
snmpCommunityTable/1, snmpCommunityTable/3,
snmpTargetAddrExtTable/3,
diff --git a/lib/snmp/src/agent/snmp_framework_mib.erl b/lib/snmp/src/agent/snmp_framework_mib.erl
index 0916e2ec74..d9bf7e8551 100644
--- a/lib/snmp/src/agent/snmp_framework_mib.erl
+++ b/lib/snmp/src/agent/snmp_framework_mib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -37,6 +37,8 @@
%%% over all known contexts.
%%%-----------------------------------------------------------------
%% External exports
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([init/0, configure/1]).
-export([intContextTable/1, intContextTable/3,
intAgentUDPPort/1, intAgentIpAddress/1,
diff --git a/lib/snmp/src/agent/snmp_generic.erl b/lib/snmp/src/agent/snmp_generic.erl
index 508aa090d9..06afa68d96 100644
--- a/lib/snmp/src/agent/snmp_generic.erl
+++ b/lib/snmp/src/agent/snmp_generic.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -18,6 +18,8 @@
%%
-module(snmp_generic).
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([variable_func/2, variable_func/3, variable_get/1, variable_set/2]).
-export([table_func/2, table_func/4,
table_set_row/5, table_set_cols/3, table_set_cols/4,
diff --git a/lib/snmp/src/agent/snmp_notification_mib.erl b/lib/snmp/src/agent/snmp_notification_mib.erl
index 16e43f05d7..1cd69b430f 100644
--- a/lib/snmp/src/agent/snmp_notification_mib.erl
+++ b/lib/snmp/src/agent/snmp_notification_mib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -18,6 +18,8 @@
%%
-module(snmp_notification_mib).
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([configure/1, reconfigure/1, invalidate_cache/0,
snmpNotifyTable/1, snmpNotifyTable/3,
snmpNotifyFilterTable/3, snmpNotifyFilterProfileTable/3,
diff --git a/lib/snmp/src/agent/snmp_standard_mib.erl b/lib/snmp/src/agent/snmp_standard_mib.erl
index 3928a8afe6..639172401d 100644
--- a/lib/snmp/src/agent/snmp_standard_mib.erl
+++ b/lib/snmp/src/agent/snmp_standard_mib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -33,6 +33,8 @@
-define(disabled, 2).
%% External exports
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([configure/1, reconfigure/1, reset/0, sys_up_time/0, sys_up_time/1,
snmp_enable_authen_traps/1, snmp_enable_authen_traps/2,
sys_object_id/1, sys_object_id/2, sys_or_table/3,
diff --git a/lib/snmp/src/agent/snmp_target_mib.erl b/lib/snmp/src/agent/snmp_target_mib.erl
index a3ac67b533..3c32d1f59f 100644
--- a/lib/snmp/src/agent/snmp_target_mib.erl
+++ b/lib/snmp/src/agent/snmp_target_mib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -18,6 +18,8 @@
%%
-module(snmp_target_mib).
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([configure/1, reconfigure/1,
snmpTargetSpinLock/1, snmpTargetSpinLock/2,
snmpTargetAddrTable/1, snmpTargetAddrTable/3,
diff --git a/lib/snmp/src/agent/snmp_user_based_sm_mib.erl b/lib/snmp/src/agent/snmp_user_based_sm_mib.erl
index 7b881f888c..f40bb1a5b9 100644
--- a/lib/snmp/src/agent/snmp_user_based_sm_mib.erl
+++ b/lib/snmp/src/agent/snmp_user_based_sm_mib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -18,6 +18,8 @@
%%
-module(snmp_user_based_sm_mib).
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([configure/1, reconfigure/1,
usmUserSpinLock/1, usmUserSpinLock/2,
usmUserTable/1, usmUserTable/3,
diff --git a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl
index 873ab00545..657207b36e 100644
--- a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl
+++ b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -18,6 +18,8 @@
%%
-module(snmp_view_based_acm_mib).
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([configure/1, reconfigure/1, table_next/2, get/3]).
-export([vacmAccessTable/1, vacmAccessTable/3,
diff --git a/lib/snmp/src/agent/snmpa_conf.erl b/lib/snmp/src/agent/snmpa_conf.erl
index b14a0c806c..b4fc716b3e 100644
--- a/lib/snmp/src/agent/snmpa_conf.erl
+++ b/lib/snmp/src/agent/snmpa_conf.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,6 +19,8 @@
-module(snmpa_conf).
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([
%% agent.conf
agent_entry/2,
diff --git a/lib/snmp/src/agent/snmpa_net_if.erl b/lib/snmp/src/agent/snmpa_net_if.erl
index 3a91cf4033..97a7a63dee 100644
--- a/lib/snmp/src/agent/snmpa_net_if.erl
+++ b/lib/snmp/src/agent/snmpa_net_if.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
+%%
%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
-%%
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
-module(snmpa_net_if).
@@ -478,12 +478,13 @@ update_req_counter_outgoing(#state{limit = Limit, rcnt = RCnt} = S,
S#state{rcnt = NewRCnt}.
-maybe_handle_recv(#state{filter = FilterMod} = S,
+maybe_handle_recv(#state{usock = Sock, filter = FilterMod} = S,
Ip, Port, Packet) ->
case (catch FilterMod:accept_recv(Ip, Port)) of
false ->
%% Drop the received packet
inc(netIfMsgInDrops),
+ active_once(Sock),
S;
_ ->
handle_recv(S, Ip, Port, Packet)
diff --git a/lib/snmp/src/agent/snmpa_target_cache.erl b/lib/snmp/src/agent/snmpa_target_cache.erl
index 6fdecacc68..2aa35aa46a 100644
--- a/lib/snmp/src/agent/snmpa_target_cache.erl
+++ b/lib/snmp/src/agent/snmpa_target_cache.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -21,6 +21,8 @@
-behaviour(gen_server).
%% External exports
+%% Avoid warning for local function demonitor/1 clashing with autoimported BIF.
+-compile({no_auto_import,[demonitor/1]}).
-export([start_link/2, stop/0, verbosity/1]).
-export([
diff --git a/lib/snmp/src/agent/snmpa_usm.erl b/lib/snmp/src/agent/snmpa_usm.erl
index ae584bb3c1..f35d1f1916 100644
--- a/lib/snmp/src/agent/snmpa_usm.erl
+++ b/lib/snmp/src/agent/snmpa_usm.erl
@@ -18,6 +18,10 @@
%%
-module(snmpa_usm).
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
+%% Avoid warning for local function error/2 clashing with autoimported BIF.
+-compile({no_auto_import,[error/2]}).
-export([
process_incoming_msg/4, process_incoming_msg/5,
generate_outgoing_msg/5, generate_outgoing_msg/6,
diff --git a/lib/snmp/src/app/snmp.appup.src b/lib/snmp/src/app/snmp.appup.src
index 9ad16ffad2..2375e3df70 100644
--- a/lib/snmp/src/app/snmp.appup.src
+++ b/lib/snmp/src/app/snmp.appup.src
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
+%%
%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
-%%
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -22,126 +22,43 @@
%% ----- U p g r a d e -------------------------------------------------------
[
- {"4.16.2",
+ {"4.17.1",
[
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmpa, soft_purge, soft_purge, [snmpa_agent]},
- {load_module, snmpa_mpd, soft_purge, soft_purge, [snmpa_usm]},
+ {load_module, snmp_community_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_framework_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_generic, soft_purge, soft_purge, []},
+ {load_module, snmp_notification_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_standard_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_target_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []},
+ {load_module, snmpa_conf, soft_purge, soft_purge, []},
+ {update, snmpa_target_cache, soft, soft_purge, soft_purge, []},
{load_module, snmpa_usm, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, []},
-
- {load_module, snmpm_mpd, soft_purge, soft_purge, []}
- ]
- },
- {"4.16.1",
- [
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
- {load_module, snmp_usm, soft_purge, soft_purge, []},
-
- {load_module, snmpa, soft_purge, soft_purge, [snmpa_agent]},
- {load_module, snmpa_mpd, soft_purge, soft_purge, [snmpa_usm]},
- {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]},
- {update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mib]},
-
- {load_module, snmpm_mpd, soft_purge, soft_purge, []},
- {update, snmpm_server, soft, soft_purge, soft_purge, []}
- ]
- },
- {"4.16",
- [
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
- {load_module, snmp_usm, soft_purge, soft_purge, []},
-
- {load_module, snmpa, soft_purge, soft_purge, [snmpa_agent]},
- {load_module, snmpa_general_db, soft_purge, soft_purge, []},
- {load_module, snmpa_mpd, soft_purge, soft_purge, [snmpa_usm]},
- {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]},
- {update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mib]},
-
- {load_module, snmpm_mpd, soft_purge, soft_purge, []},
- {update, snmpm_net_if, soft, soft_purge, soft_purge, []},
- {update, snmpm_server, soft, soft_purge, soft_purge, []}
- ]
- },
- {"4.15",
- [
- {load_module, snmp_config, soft_purge, soft_purge, []},
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
- {load_module, snmp_usm, soft_purge, soft_purge, []},
-
- {load_module, snmpa, soft_purge, soft_purge, [snmp_log, snmpa_agent]},
- {load_module, snmpa_general_db, soft_purge, soft_purge, []},
- {load_module, snmpa_mpd, soft_purge, soft_purge, [snmpa_usm]},
- {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]},
- {update, snmpa_net_if, {advanced, upgrade_from_pre_4_16},
- soft_purge, soft_purge, [snmpa_agent, snmp_log]},
- {update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mib]},
-
- {load_module, snmpm_mpd, soft_purge, soft_purge, []},
- {update, snmpm_net_if, {advanced, upgrade_from_pre_4_16},
- soft_purge, soft_purge, [snmpm_config, snmp_log]},
+ {load_module, snmpm, soft_purge, soft_purge, []},
+ {load_module, snmpm_conf, soft_purge, soft_purge, []},
{update, snmpm_config, soft, soft_purge, soft_purge, []},
- {update, snmpm_server, soft, soft_purge, soft_purge, []}
+ {load_module, snmpm_usm, soft_purge, soft_purge, []}
]
- },
- {"4.14",
+ },
+ {"4.17",
[
- {load_module, snmp_config, soft_purge, soft_purge, []},
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
- {load_module, snmp_usm, soft_purge, soft_purge, []},
-
- {load_module, snmpa, soft_purge, soft_purge, [snmp_log, snmpa_agent]},
- {load_module, snmpa_general_db, soft_purge, soft_purge, []},
- {load_module, snmpa_mpd, soft_purge, soft_purge, [snmpa_usm]},
- {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]},
- {update, snmpa_net_if, {advanced, upgrade_from_pre_4_16},
- soft_purge, soft_purge, [snmp_log, snmpa_agent]},
- {update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mib]},
-
- {load_module, snmpm_mpd, soft_purge, soft_purge, []},
- {load_module, snmpm_user, soft_purge, soft_purge, []},
- {load_module, snmpm_user_default, soft_purge, soft_purge, [snmpm_user]},
- {update, snmpm_net_if, {advanced, upgrade_from_pre_4_16},
- soft_purge, soft_purge, [snmpm_config, snmp_log]},
+ {load_module, snmp_community_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_framework_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_generic, soft_purge, soft_purge, []},
+ {load_module, snmp_notification_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_standard_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_target_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []},
+ {load_module, snmpa_conf, soft_purge, soft_purge, []},
+ {update, snmpa_target_cache, soft, soft_purge, soft_purge, []},
+ {load_module, snmpa_usm, soft_purge, soft_purge, []},
+ {load_module, snmpm, soft_purge, soft_purge, []},
+ {load_module, snmpm_conf, soft_purge, soft_purge, []},
{update, snmpm_config, soft, soft_purge, soft_purge, []},
- {update, snmpm_server, soft, soft_purge, soft_purge,
- [snmpm_user_default]}
- ]
- },
- {"4.13.5",
- [
- {load_module, snmp_config, soft_purge, soft_purge, []},
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
- {load_module, snmp_usm, soft_purge, soft_purge, []},
-
- {load_module, snmpa, soft_purge, soft_purge, [snmp_log, snmpa_agent]},
- {load_module, snmpa_general_db, soft_purge, soft_purge, []},
- {load_module, snmpa_mib_data, soft_purge, soft_purge, []},
- {load_module, snmpa_mpd, soft_purge, soft_purge, [snmpa_usm]},
- {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]},
- {update, snmpa_net_if, {advanced, upgrade_from_pre_4_16},
- soft_purge, soft_purge, [snmpa_agent, snmp_log]},
- {update, snmpa_mib, soft, soft_purge, soft_purge, [snmpa_mib_data]},
- {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mib]},
-
- {load_module, snmpm_mpd, soft_purge, soft_purge, []},
- {load_module, snmpm_user, soft_purge, soft_purge, []},
- {load_module, snmpm_user_default, soft_purge, soft_purge, [snmpm_user]},
- {update, snmpm_net_if, {advanced, upgrade_from_pre_4_14},
- soft_purge, soft_purge, [snmpm_config, snmp_log]},
- {update, snmpm_config, soft, soft_purge, soft_purge, []},
- {update, snmpm_server, soft, soft_purge, soft_purge, [snmpm_user_default]},
- {add_module, snmpm_net_if_filter},
- {add_module, snmpm_network_interface_filter}
+ {load_module, snmpm_usm, soft_purge, soft_purge, []},
+ {load_module, snmpa_net_if, soft_purge, soft_purge, []}
]
}
],
@@ -149,128 +66,43 @@
%% ------D o w n g r a d e ---------------------------------------------------
[
- {"4.16.2",
+ {"4.17.1",
[
- {load_module, snmp_log, soft_purge, soft_purge, []},
-
- {load_module, snmpa, soft_purge, soft_purge, [snmpa_agent]},
- {load_module, snmpa_mpd, soft_purge, soft_purge, [snmpa_usm]},
+ {load_module, snmp_community_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_framework_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_generic, soft_purge, soft_purge, []},
+ {load_module, snmp_notification_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_standard_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_target_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []},
+ {load_module, snmpa_conf, soft_purge, soft_purge, []},
+ {update, snmpa_target_cache, soft, soft_purge, soft_purge, []},
{load_module, snmpa_usm, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, []},
-
- {load_module, snmpm_mpd, soft_purge, soft_purge, []}
- ]
- },
- {"4.16.1",
- [
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
- {load_module, snmp_usm, soft_purge, soft_purge, []},
-
- {load_module, snmpa, soft_purge, soft_purge, [snmpa_agent]},
- {load_module, snmpa_mpd, soft_purge, soft_purge, [snmpa_usm]},
- {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]},
- {update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mib]},
-
- {load_module, snmpm_mpd, soft_purge, soft_purge, []},
- {update, snmpm_server, soft, soft_purge, soft_purge, []}
- ]
- },
- {"4.16",
- [
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
- {load_module, snmp_usm, soft_purge, soft_purge, []},
-
- {load_module, snmpa, soft_purge, soft_purge, [snmpa_agent]},
- {load_module, snmpa_general_db, soft_purge, soft_purge, []},
- {load_module, snmpa_mpd, soft_purge, soft_purge, [snmpa_usm]},
- {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]},
- {update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mib]},
-
- {load_module, snmpm_mpd, soft_purge, soft_purge, []},
- {update, snmpm_net_if, soft, soft_purge, soft_purge, []},
- {update, snmpm_server, soft, soft_purge, soft_purge, []}
- ]
- },
- {"4.15",
- [
- {load_module, snmp_config, soft_purge, soft_purge, []},
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
- {load_module, snmp_usm, soft_purge, soft_purge, []},
-
- {load_module, snmpa, soft_purge, soft_purge, [snmpa_agent, snmp_log]},
- {load_module, snmpa_general_db, soft_purge, soft_purge, []},
- {load_module, snmpa_mpd, soft_purge, soft_purge, [snmpa_usm]},
- {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]},
- {update, snmpa_net_if, {advanced, downgrade_to_pre_4_16},
- soft_purge, soft_purge, [snmpa_agent, snmp_log]},
- {update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mib]},
-
- {load_module, snmpm_mpd, soft_purge, soft_purge, []},
- {update, snmpm_net_if, {advanced, downgrade_to_pre_4_16},
- soft_purge, soft_purge, [snmpm_config, snmp_log]},
+ {load_module, snmpm, soft_purge, soft_purge, []},
+ {load_module, snmpm_conf, soft_purge, soft_purge, []},
{update, snmpm_config, soft, soft_purge, soft_purge, []},
- {update, snmpm_server, soft, soft_purge, soft_purge, []}
+ {load_module, snmpm_usm, soft_purge, soft_purge, []}
]
},
- {"4.14",
+ {"4.17",
[
- {load_module, snmp_config, soft_purge, soft_purge, []},
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
- {load_module, snmp_usm, soft_purge, soft_purge, []},
-
- {load_module, snmpa, soft_purge, soft_purge, [snmpa_agent, snmp_log]},
- {load_module, snmpa_general_db, soft_purge, soft_purge, []},
- {load_module, snmpa_mpd, soft_purge, soft_purge, [snmpa_usm]},
- {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]},
- {update, snmpa_net_if, {advanced, downgrade_to_pre_4_16},
- soft_purge, soft_purge, [snmpa_agent, snmp_log]},
- {update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mib]},
-
- {load_module, snmpm_mpd, soft_purge, soft_purge, []},
- {load_module, snmpm_user, soft_purge, soft_purge, []},
- {load_module, snmpm_user_default, soft_purge, soft_purge, [snmpm_user]},
- {update, snmpm_net_if, {advanced, downgrade_to_pre_4_16},
- soft_purge, soft_purge, [snmpm_config, snmp_log]},
+ {load_module, snmp_community_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_framework_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_generic, soft_purge, soft_purge, []},
+ {load_module, snmp_notification_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_standard_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_target_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []},
+ {load_module, snmpa_conf, soft_purge, soft_purge, []},
+ {update, snmpa_target_cache, soft, soft_purge, soft_purge, []},
+ {load_module, snmpa_usm, soft_purge, soft_purge, []},
+ {load_module, snmpm, soft_purge, soft_purge, []},
+ {load_module, snmpm_conf, soft_purge, soft_purge, []},
{update, snmpm_config, soft, soft_purge, soft_purge, []},
- {update, snmpm_server, soft, soft_purge, soft_purge,
- [snmpm_user_default]}
- ]
- },
- {"4.13.5",
- [
- {load_module, snmp_config, soft_purge, soft_purge, []},
- {load_module, snmp_log, soft_purge, soft_purge, []},
- {load_module, snmp_pdus, soft_purge, soft_purge, []},
- {load_module, snmp_usm, soft_purge, soft_purge, []},
-
- {load_module, snmpa, soft_purge, soft_purge, [snmp_log, snmpa_agent]},
- {load_module, snmpa_general_db, soft_purge, soft_purge, []},
- {load_module, snmpa_mib_data, soft_purge, soft_purge, []},
- {load_module, snmpa_mpd, soft_purge, soft_purge, [snmpa_usm]},
- {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]},
- {update, snmpa_net_if, {advanced, downgrade_to_pre_4_16},
- soft_purge, soft_purge, [snmpa_agent, snmp_log]},
- {update, snmpa_mib, soft, soft_purge, soft_purge, [snmpa_mib_data]},
- {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mib]},
-
- {load_module, snmpm_mpd, soft_purge, soft_purge, []},
- {load_module, snmpm_user, soft_purge, soft_purge, []},
- {load_module, snmpm_user_default, soft_purge, soft_purge, [snmpm_user]},
- {update, snmpm_net_if, {advanced, downgrade_to_pre_4_14},
- soft_purge, soft_purge, [snmpm_config, snmp_log]},
- {update, snmpm_config, soft, soft_purge, soft_purge, []},
- {update, snmpm_server, soft, soft_purge, soft_purge, [snmpm_user_default]},
-
- {remove, {snmpm_net_if_filter, soft_purge, brutal_purge}},
- {remove, {snmpm_network_interface_filter, soft_purge, brutal_purge}}
+ {load_module, snmpm_usm, soft_purge, soft_purge, []},
+ {load_module, snmpa_net_if, soft_purge, soft_purge, []}
]
}
]
diff --git a/lib/snmp/src/compile/snmpc_lib.erl b/lib/snmp/src/compile/snmpc_lib.erl
index 4e5bc69f81..4490412e84 100644
--- a/lib/snmp/src/compile/snmpc_lib.erl
+++ b/lib/snmp/src/compile/snmpc_lib.erl
@@ -20,6 +20,8 @@
-module(snmpc_lib).
%% API
+%% Avoid warning for local function error/2 clashing with autoimported BIF.
+-compile({no_auto_import,[error/2]}).
-export([test_father/4, make_ASN1type/1, import/1, makeInternalNode2/2,
is_consistent/1, resolve_defval/1, make_variable_info/1,
check_trap_name/3, make_table_info/4, get_final_mib/2, set_dir/2,
diff --git a/lib/snmp/src/manager/snmpm.erl b/lib/snmp/src/manager/snmpm.erl
index 141addf440..5b6321b4c3 100644
--- a/lib/snmp/src/manager/snmpm.erl
+++ b/lib/snmp/src/manager/snmpm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -24,6 +24,8 @@
%%----------------------------------------------------------------------
%% User interface
+%% Avoid warning for local function demonitor/1 clashing with autoimported BIF.
+-compile({no_auto_import,[demonitor/1]}).
-export([
%%
%% Management API
diff --git a/lib/snmp/src/manager/snmpm_conf.erl b/lib/snmp/src/manager/snmpm_conf.erl
index 75f9c09477..e50508c489 100644
--- a/lib/snmp/src/manager/snmpm_conf.erl
+++ b/lib/snmp/src/manager/snmpm_conf.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -21,6 +21,8 @@
-include_lib("kernel/include/file.hrl").
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([
%% manager.conf
manager_entry/2,
diff --git a/lib/snmp/src/manager/snmpm_config.erl b/lib/snmp/src/manager/snmpm_config.erl
index b976e8f568..fd6da3e71a 100644
--- a/lib/snmp/src/manager/snmpm_config.erl
+++ b/lib/snmp/src/manager/snmpm_config.erl
@@ -28,6 +28,8 @@
-behaviour(gen_server).
%% External exports
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([start_link/1, stop/0, is_started/0]).
-export([register_user/4, unregister_user/1,
which_users/0,
diff --git a/lib/snmp/src/manager/snmpm_usm.erl b/lib/snmp/src/manager/snmpm_usm.erl
index 8cb3062d4b..449127844a 100644
--- a/lib/snmp/src/manager/snmpm_usm.erl
+++ b/lib/snmp/src/manager/snmpm_usm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -23,6 +23,10 @@
-module(snmpm_usm).
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
+%% Avoid warning for local function error/2 clashing with autoimported BIF.
+-compile({no_auto_import,[error/2]}).
-export([init/0,
reset/0,
process_incoming_msg/4, generate_outgoing_msg/5]).
diff --git a/lib/snmp/src/misc/snmp_conf.erl b/lib/snmp/src/misc/snmp_conf.erl
index 63762ac17b..4d2f5d8f92 100644
--- a/lib/snmp/src/misc/snmp_conf.erl
+++ b/lib/snmp/src/misc/snmp_conf.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -23,6 +23,8 @@
%% External exports
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([read_files/2, read/2]).
%% Basic (type) check functions
diff --git a/lib/snmp/src/misc/snmp_config.erl b/lib/snmp/src/misc/snmp_config.erl
index c066680160..25350e08cb 100644
--- a/lib/snmp/src/misc/snmp_config.erl
+++ b/lib/snmp/src/misc/snmp_config.erl
@@ -22,6 +22,8 @@
-include_lib("kernel/include/file.hrl").
-include("snmp_types.hrl").
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([config/0]).
-export([write_config_file/4, append_config_file/4, read_config_file/3]).
diff --git a/lib/snmp/src/misc/snmp_usm.erl b/lib/snmp/src/misc/snmp_usm.erl
index 3508f9e1c2..df2c1f0b18 100644
--- a/lib/snmp/src/misc/snmp_usm.erl
+++ b/lib/snmp/src/misc/snmp_usm.erl
@@ -19,6 +19,8 @@
-module(snmp_usm).
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([passwd2localized_key/3, localize_key/3]).
-export([auth_in/4, auth_out/4, set_msg_auth_params/3]).
-export([des_encrypt/3, des_decrypt/3]).
diff --git a/lib/snmp/vsn.mk b/lib/snmp/vsn.mk
index 4ca1fb7901..1229b12ae2 100644
--- a/lib/snmp/vsn.mk
+++ b/lib/snmp/vsn.mk
@@ -1,57 +1,3 @@
-#-*-makefile-*- ; force emacs to enter makefile-mode
-
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2010. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-
-SNMP_VSN = 4.17
+SNMP_VSN = 4.18
PRE_VSN =
APP_VSN = "snmp-$(SNMP_VSN)$(PRE_VSN)"
-
-TICKETS = OTP-8478
-
-TICKETS_4_16_2 = \
- OTP-8563 \
- OTP-8574 \
- OTP-8594 \
- OTP-8595 \
- OTP-8646 \
- OTP-8648
-
-TICKETS_4_16_1 = \
- OTP-8480 \
- OTP-8481
-
-TICKETS_4_16 = \
- OTP-8395 \
- OTP-8433 \
- OTP-8442
-
-TICKETS_4_15 = \
- OTP-8229 \
- OTP-8249
-
-TICKETS_4_14 = \
- OTP-8223 \
- OTP-8228 \
- OTP-8237
-
-TICKETS_4_13_5 = \
- OTP-8116 \
- OTP-8120 \
- OTP-8181 \
- OTP-8182
-
diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml
index 7c8735cf56..9bedd446f4 100644
--- a/lib/ssh/doc/src/notes.xml
+++ b/lib/ssh/doc/src/notes.xml
@@ -29,7 +29,81 @@
<file>notes.xml</file>
</header>
- <section><title>Ssh 2.0</title>
+<section><title>Ssh 2.0.3</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The fix regarding OTP-8849 was not included in the
+ previous version as stated.</p>
+ <p>
+ Own Id: OTP-8918</p>
+ </item>
+ </list>
+ </section>
+</section>
+
+<section><title>Ssh 2.0.2</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The ssh_system_sup did not catch noproc and shutdown
+ messages.</p>
+ <p>
+ Own Id: OTP-8863</p>
+ </item>
+ <item>
+ <p>
+ In some cases a crash report was generated when a
+ connection was closing down. This was caused by a race
+ condition between two processes.</p>
+ <p>
+ Own Id: OTP-8881 Aux Id: seq11656, seq11648 </p>
+ </item>
+ </list>
+ </section>
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ SSH no longer use deprecated public_key functions.</p>
+ <p>
+ Own Id: OTP-8849</p>
+ </item>
+ </list>
+ </section>
+ </section>
+ <section><title>Ssh 2.0.1</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ SSH in some cases terminated channels with reason normal
+ when it should have been shutdown.</p>
+ <p>
+ Own Id: OTP-8714</p>
+ </item>
+ <item>
+ <p>
+ SSH in some cases generated a crash report when a channel
+ was closed in a normal way.</p>
+ <p>
+ Own Id: OTP-8735 Aux Id: seq11615 </p>
+ </item>
+ <item>
+ <p>
+ The processes ssh_subsystem_sup and one ssh_channel_sup
+ was not terminated when a connection was closed.</p>
+ <p>
+ Own Id: OTP-8807</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 2.0</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/ssh/src/ssh.appup.src b/lib/ssh/src/ssh.appup.src
index 21f7508555..9c806bcd03 100644
--- a/lib/ssh/src/ssh.appup.src
+++ b/lib/ssh/src/ssh.appup.src
@@ -19,9 +19,13 @@
{"%VSN%",
[
+ {"2.0.2", [{load_module, ssh_file, soft_purge, soft_purge, []}]},
+ {"2.0.1", [{restart_application, ssh}]}
],
[
- ]
+ {"2.0.2", [{load_module, ssh_file, soft_purge, soft_purge, []}]},
+ {"2.0.1", [{restart_application, ssh}]}
+ ]
}.
diff --git a/lib/ssh/src/ssh_channel.erl b/lib/ssh/src/ssh_channel.erl
index 8a49a44a6c..dcb2d69290 100644
--- a/lib/ssh/src/ssh_channel.erl
+++ b/lib/ssh/src/ssh_channel.erl
@@ -238,9 +238,19 @@ handle_info(Msg, #state{cm = ConnectionManager, channel_cb = Module,
{noreply, State#state{channel_state = ChannelState}};
{ok, ChannelState, Timeout} ->
{noreply, State#state{channel_state = ChannelState}, Timeout};
+ {stop, Reason, ChannelState} when is_atom(Reason)->
+ {stop, Reason, State#state{close_sent = true,
+ channel_state = ChannelState}};
{stop, ChannelId, ChannelState} ->
- ssh_connection:close(ConnectionManager, ChannelId),
- {stop, normal, State#state{close_sent = true,
+ Reason =
+ case Msg of
+ {'EXIT', _Pid, shutdown} ->
+ shutdown;
+ _ ->
+ normal
+ end,
+ (catch ssh_connection:close(ConnectionManager, ChannelId)),
+ {stop, Reason, State#state{close_sent = true,
channel_state = ChannelState}}
end.
diff --git a/lib/ssh/src/ssh_cli.erl b/lib/ssh/src/ssh_cli.erl
index e3b6ffa125..cb78acb84c 100644
--- a/lib/ssh/src/ssh_cli.erl
+++ b/lib/ssh/src/ssh_cli.erl
@@ -415,14 +415,12 @@ start_shell(ConnectionManager, State) ->
Shell = State#state.shell,
ShellFun = case is_function(Shell) of
true ->
+ {ok, User} =
+ ssh_userreg:lookup_user(ConnectionManager),
case erlang:fun_info(Shell, arity) of
{arity, 1} ->
- {ok, User} =
- ssh_userreg:lookup_user(ConnectionManager),
fun() -> Shell(User) end;
{arity, 2} ->
- {ok, User} =
- ssh_userreg:lookup_user(ConnectionManager),
{ok, PeerAddr} =
ssh_connection_manager:peer_addr(ConnectionManager),
fun() -> Shell(User, PeerAddr) end;
@@ -437,10 +435,28 @@ start_shell(ConnectionManager, State) ->
State#state{group = Group, buf = empty_buf()}.
start_shell(_ConnectionManager, Cmd, #state{exec={M, F, A}} = State) ->
- Group = group:start(self(), {M, F, A++[Cmd]}, [{echo,false}]),
+ Group = group:start(self(), {M, F, A++[Cmd]}, [{echo, false}]),
+ State#state{group = Group, buf = empty_buf()};
+start_shell(ConnectionManager, Cmd, #state{exec=Shell} = State) when is_function(Shell) ->
+ {ok, User} =
+ ssh_userreg:lookup_user(ConnectionManager),
+ ShellFun =
+ case erlang:fun_info(Shell, arity) of
+ {arity, 1} ->
+ fun() -> Shell(Cmd) end;
+ {arity, 2} ->
+ fun() -> Shell(Cmd, User) end;
+ {arity, 3} ->
+ {ok, PeerAddr} =
+ ssh_connection_manager:peer_addr(ConnectionManager),
+ fun() -> Shell(Cmd, User, PeerAddr) end;
+ _ ->
+ Shell
+ end,
+ Echo = get_echo(State#state.pty),
+ Group = group:start(self(), ShellFun, [{echo,Echo}]),
State#state{group = Group, buf = empty_buf()}.
-
% Pty can be undefined if the client never sets any pty options before
% starting the shell.
get_echo(undefined) ->
diff --git a/lib/ssh/src/ssh_connection_controler.erl b/lib/ssh/src/ssh_connection_controler.erl
index 636ecba532..ca3e62dc83 100644
--- a/lib/ssh/src/ssh_connection_controler.erl
+++ b/lib/ssh/src/ssh_connection_controler.erl
@@ -126,8 +126,8 @@ handle_cast(_, State) ->
%% handle_info(ssh_connected, State) ->
%% {stop, normal, State};
%% Servant termination.
-handle_info({'EXIT', _Pid, normal}, State) ->
- {stop, normal, State}.
+handle_info({'EXIT', _Pid, Reason}, State) ->
+ {stop, Reason, State}.
%%-----------------------------------------------------------------
%% Func: code_change/3
diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl
index d46002c494..0ba11b0a26 100644
--- a/lib/ssh/src/ssh_connection_handler.erl
+++ b/lib/ssh/src/ssh_connection_handler.erl
@@ -705,11 +705,19 @@ generate_event(<<?BYTE(Byte), _/binary>> = Msg, StateName,
Byte == ?SSH_MSG_CHANNEL_REQUEST;
Byte == ?SSH_MSG_CHANNEL_SUCCESS;
Byte == ?SSH_MSG_CHANNEL_FAILURE ->
- ssh_connection_manager:event(Pid, Msg),
- State = generate_event_new_state(State0, EncData),
- next_packet(State),
- {next_state, StateName, State};
+ try
+ ssh_connection_manager:event(Pid, Msg),
+ State = generate_event_new_state(State0, EncData),
+ next_packet(State),
+ {next_state, StateName, State}
+ catch
+ exit:{noproc, _Reason} ->
+ Report = io_lib:format("~p Connection Handler terminated: ~p~n",
+ [self(), Pid]),
+ error_logger:info_report(Report),
+ {stop, normal, State0}
+ end;
generate_event(Msg, StateName, State0, EncData) ->
Event = ssh_bits:decode(Msg),
State = generate_event_new_state(State0, EncData),
diff --git a/lib/ssh/src/ssh_connection_manager.erl b/lib/ssh/src/ssh_connection_manager.erl
index cffeade485..6bf89224cf 100644
--- a/lib/ssh/src/ssh_connection_manager.erl
+++ b/lib/ssh/src/ssh_connection_manager.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
+%%
%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
-%%
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
%%
@@ -146,6 +146,8 @@ adjust_window(ConnectionManager, Channel, Bytes) ->
close(ConnectionManager, ChannelId) ->
try call(ConnectionManager, {close, ChannelId}) of
ok ->
+ ok;
+ {error,normal} ->
ok
catch
exit:{noproc, _} ->
@@ -155,6 +157,8 @@ close(ConnectionManager, ChannelId) ->
stop(ConnectionManager) ->
try call(ConnectionManager, stop) of
ok ->
+ ok;
+ {error,normal} ->
ok
catch
exit:{noproc, _} ->
@@ -556,13 +560,18 @@ handle_info({'EXIT', _, _}, State) ->
%% The return value is ignored.
%%--------------------------------------------------------------------
terminate(Reason, #state{connection_state =
- #connection{requests = Requests},
+ #connection{requests = Requests,
+ sub_system_supervisor = SubSysSup},
opts = Opts}) ->
SSHOpts = proplists:get_value(ssh_opts, Opts),
disconnect_fun(Reason, SSHOpts),
(catch lists:foreach(fun({_, From}) ->
gen_server:reply(From, {error, connection_closed})
end, Requests)),
+ Address = proplists:get_value(address, Opts),
+ Port = proplists:get_value(port, Opts),
+ SystemSup = ssh_system_sup:system_supervisor(Address, Port),
+ ssh_system_sup:stop_subsystem(SystemSup, SubSysSup),
ok.
%%--------------------------------------------------------------------
@@ -593,7 +602,9 @@ call(Pid, Msg, Timeout) ->
Result
catch
exit:{timeout, _} ->
- {error, timeout}
+ {error, timeout};
+ exit:{normal, _} ->
+ {error, normal}
end.
cast(Pid, Msg) ->
diff --git a/lib/ssh/src/ssh_file.erl b/lib/ssh/src/ssh_file.erl
index 5572349fe7..13722656db 100755
--- a/lib/ssh/src/ssh_file.erl
+++ b/lib/ssh/src/ssh_file.erl
@@ -198,12 +198,17 @@ read_public_key_v1(File) ->
%% pem_type("ssh-rsa") -> "RSA".
read_private_key_v2(File, Type) ->
- case catch (public_key:pem_to_der(File)) of
- {ok, [{_, Bin, not_encrypted}]} ->
- decode_private_key_v2(Bin, Type);
- Error -> %% Note we do not handle password encrypted keys at the moment
- {error, Error}
- end.
+ case file:read_file(File) of
+ {ok, PemBin} ->
+ case catch (public_key:pem_decode(PemBin)) of
+ [{_, Bin, not_encrypted}] ->
+ decode_private_key_v2(Bin, Type);
+ Error -> %% Note we do not handle password encrypted keys at the moment
+ {error, Error}
+ end;
+ {error, Reason} ->
+ {error, Reason}
+ end.
%% case file:read_file(File) of
%% {ok,Bin} ->
%% case read_pem(binary_to_list(Bin), pem_type(Type)) of
diff --git a/lib/ssh/src/ssh_system_sup.erl b/lib/ssh/src/ssh_system_sup.erl
index 40db2e4adf..920baaadef 100644
--- a/lib/ssh/src/ssh_system_sup.erl
+++ b/lib/ssh/src/ssh_system_sup.erl
@@ -33,7 +33,8 @@
stop_system/2, system_supervisor/2,
subsystem_supervisor/1, channel_supervisor/1,
connection_supervisor/1,
- acceptor_supervisor/1, start_subsystem/2, restart_subsystem/2, restart_acceptor/2]).
+ acceptor_supervisor/1, start_subsystem/2, restart_subsystem/2,
+ restart_acceptor/2, stop_subsystem/2]).
%% Supervisor callback
-export([init/1]).
@@ -83,6 +84,23 @@ start_subsystem(SystemSup, Options) ->
Spec = ssh_subsystem_child_spec(Options),
supervisor:start_child(SystemSup, Spec).
+stop_subsystem(SystemSup, SubSys) ->
+ case catch lists:keyfind(SubSys, 2, supervisor:which_children(SystemSup)) of
+ false ->
+ {error, not_found};
+ {Id, _, _, _} ->
+ spawn(fun() -> supervisor:terminate_child(SystemSup, Id),
+ supervisor:delete_child(SystemSup, Id) end),
+ ok;
+ {'EXIT', {noproc, _}} ->
+ %% Already terminated; probably shutting down.
+ ok;
+ {'EXIT', {shutdown, _}} ->
+ %% Already shutting down.
+ ok
+ end.
+
+
restart_subsystem(Address, Port) ->
SysSupName = make_name(Address, Port),
SubSysName = id(ssh_subsystem_sup, Address, Port),
diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk
index ccdbfe4f9a..db03168ad9 100644
--- a/lib/ssh/vsn.mk
+++ b/lib/ssh/vsn.mk
@@ -1,84 +1,5 @@
#-*-makefile-*- ; force emacs to enter makefile-mode
-SSH_VSN = 2.0
+SSH_VSN = 2.0.3
APP_VSN = "ssh-$(SSH_VSN)"
-TICKETS = OTP-8524 \
- OTP-8534 \
- OTP-8535 \
- OTP-8550 \
- OTP-8596 \
- OTP-8644 \
- OTP-8645
-
-TICKETS_1.1.8 = OTP-8356 \
- OTP-8401
-
-TICKETS_1.1.7 = OTP-8121 \
- OTP-8277 \
- OTP-8278 \
- OTP-8201
-
-TICKETS_1.1.6 = OTP-8110 \
- OTP-8162 \
- OTP-8173 \
- OTP-8174 \
- OTP-8175 \
- OTP-8176
-
-TICKETS_1.1.5 = OTP-8159 \
- OTP-8160 \
- OTP-8161
-
-TICKETS_1.1.4 = OTP-8071
-
-TICKETS_1.1.3 = OTP-7996 \
- OTP-8034 \
- OTP-8035
-
-TICKETS_1.1.2 = OTP-7914 \
- OTP-7917 \
- OTP-7918 \
- OTP-7921 \
- OTP-7919 \
- OTP-7930 \
- OTP-7957
-
-TICKETS_1.1.1 = OTP-7828 \
- OTP-7795 \
- OTP-7807 \
- OTP-7808 \
- OTP-7809
-
-TICKETS_1.1 = OTP-7676 \
- OTP-7683 \
- OTP-7685 \
- OTP-7766 \
- OTP-7767 \
- OTP-7768 \
- OTP-7770 \
- OTP-7456 \
- OTP-7769 \
- OTP-7516 \
- OTP-7645 \
-
-TICKETS_1.0.2 = \
- OTP-7141\
-
-TICKETS_1.0.1 = \
- OTP-7318 \
- OTP-7305 \
- OTP-7564 \
- OTP-7565 \
- OTP-7566 \
-
-TICKETS_1.0 = \
- OTP-7485 \
- OTP-7504 \
- OTP-7356 \
- OTP-7502 \
- OTP-7503
-
-TICKETS_0.9.9.6 = \
- OTP-7246 \
- OTP-7247 \ \ No newline at end of file
diff --git a/lib/ssl/Makefile b/lib/ssl/Makefile
index b8b51270c9..daad7dc3e6 100644
--- a/lib/ssl/Makefile
+++ b/lib/ssl/Makefile
@@ -24,22 +24,8 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
#
# Macros
#
-ifeq ($(findstring win32,$(TARGET)),win32)
-ifeq ($(HOST_OS),)
-HOST_OS := $(shell $(ERL_TOP)/erts/autoconf/config.guess)
-endif
-ifeq ($(findstring solaris,$(HOST_OS)),solaris)
-SKIP_BUILDING_BINARIES := true
-endif
-else
-SKIP_BUILDING_BINARIES := false
-endif
-
-ifeq ($(SKIP_BUILDING_BINARIES), true)
-SUB_DIRECTORIES = src c_src doc/src
-else
+
SUB_DIRECTORIES = src c_src doc/src examples/certs examples/src
-endif
include vsn.mk
VSN = $(SSL_VSN)
diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml
index 95e968aa22..756c0d1b1f 100644
--- a/lib/ssl/doc/src/notes.xml
+++ b/lib/ssl/doc/src/notes.xml
@@ -31,7 +31,156 @@
<p>This document describes the changes made to the SSL application.
</p>
- <section><title>SSL 4.0</title>
+ <section><title>SSL 4.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Updated ssl to ignore CA certs that violate the asn1-spec
+ for a certificate, and updated public key asn1 spec to
+ handle inherited DSS-params.</p>
+ <p>
+ Own Id: OTP-7884</p>
+ </item>
+ <item>
+ <p>
+ Changed ssl implementation to retain backwards
+ compatibility for old option {verify, 0} that shall be
+ equivalent to {verify, verify_none}, also separate the
+ cases unknown ca and selfsigned peer cert, and restored
+ return value of deprecated function
+ public_key:pem_to_der/1.</p>
+ <p>
+ Own Id: OTP-8858</p>
+ </item>
+ <item>
+ <p>
+ Changed the verify fun so that it differentiate between
+ the peer certificate and CA certificates by using
+ valid_peer or valid as the second argument to the verify
+ fun. It may not always be trivial or even possible to
+ know when the peer certificate is reached otherwise.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-8873</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 4.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The server now verifies the client certificate verify
+ message correctly, instead of causing a case-clause.</p>
+ <p>
+ Own Id: OTP-8721</p>
+ </item>
+ <item>
+ <p>
+ The client hello message now always include ALL available
+ cipher suites (or those specified by the ciphers option).
+ Previous implementation would filter them based on the
+ client certificate key usage extension (such filtering
+ only makes sense for the server certificate).</p>
+ <p>
+ Own Id: OTP-8772</p>
+ </item>
+ <item>
+ <p>
+ Fixed handling of the option {mode, list} that was broken
+ for some packet types for instance line.</p>
+ <p>
+ Own Id: OTP-8785</p>
+ </item>
+ <item>
+ <p>
+ Empty packets were not delivered to the client.</p>
+ <p>
+ Own Id: OTP-8790</p>
+ </item>
+ <item>
+ <p> Building in a source tree without prebuilt platform
+ independent build results failed on the SSL examples
+ when: </p> <list><item> cross building. This has been
+ solved by not building the SSL examples during a cross
+ build. </item><item> building on Windows. </item></list>
+ <p>
+ Own Id: OTP-8791</p>
+ </item>
+ <item>
+ <p>
+ Fixed a handshake error which occurred on some ssl
+ implementations.</p>
+ <p>
+ Own Id: OTP-8793</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Revise the public_key API - Cleaned up and documented the
+ public_key API to make it useful for general use, also
+ changed ssl to use the new API.</p>
+ <p>
+ Own Id: OTP-8722</p>
+ </item>
+ <item>
+ <p>
+ Added support for inputing certificates and keys directly
+ in DER format these options will override the pem-file
+ options if specified.</p>
+ <p>
+ Own Id: OTP-8723</p>
+ </item>
+ <item>
+ <p>
+ To gain interoperability ssl will not check for padding
+ errors when using TLS 1.0. It is first in TLS 1.1 that
+ checking the padding is an requirement.</p>
+ <p>
+ Own Id: OTP-8740</p>
+ </item>
+ <item>
+ <p>
+ Changed the semantics of the verify_fun option in the
+ ssl-application so that it takes care of both application
+ handling of path validation errors and verification of
+ application specific extensions. This means that it is
+ now possible for the server application in verify_peer
+ mode to handle path validation errors. This change moved
+ some functionality earlier in ssl to the public_key
+ application.</p>
+ <p>
+ Own Id: OTP-8770</p>
+ </item>
+ <item>
+ <p>
+ Added the functionality so that the verification fun will
+ be called when a certificate is considered valid by the
+ path validation to allow access to each certificate in
+ the path to the user application. Also try to verify
+ subject-AltName, if unable to verify it let the
+ application verify it.</p>
+ <p>
+ Own Id: OTP-8825</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 4.0</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml
index def61bcf03..511f1e0bb2 100644
--- a/lib/ssl/doc/src/ssl.xml
+++ b/lib/ssl/doc/src/ssl.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE erlref SYSTEM "erlref.dtd">
<erlref>
@@ -69,10 +69,13 @@
</p>
<p> <c>ssloption() = {verify, verify_type()} |
+ {verify_fun, {fun(), term()}} |
{fail_if_no_peer_cert, boolean()}
{depth, integer()} |
- {certfile, path()} | {keyfile, path()} | {password, string()} |
- {cacertfile, path()} | {dhfile, path()} | {ciphers, ciphers()} |
+ {cert, der_bin()}| {certfile, path()} |
+ {key, der_bin()} | {keyfile, path()} | {password, string()} |
+ {cacerts, [der_bin()]} | {cacertfile, path()} |
+ |{dh, der_bin()} | {dhfile, path()} | {ciphers, ciphers()} |
{ssl_imp, ssl_imp()} | {reuse_sessions, boolean()} | {reuse_session, fun()}
</c></p>
@@ -91,6 +94,8 @@
<p><c>verify_type() = verify_none | verify_peer</c></p>
<p><c>path() = string() - representing a file path.</c></p>
+
+ <p><c>der_bin() = binary() -Asn1 DER encoded entity as an erlang binary.</c></p>
<p><c>host() = hostname() | ipaddress()</c></p>
@@ -109,7 +114,7 @@
<p><c>ciphersuite() =
{key_exchange(), cipher(), hash()}</c></p>
- <p><c>key_exchange() = rsa | dhe_dss | dhe_rsa
+ <p><c>key_exchange() = rsa | dhe_dss | dhe_rsa | dh_anon
</c></p>
<p><c>cipher() = rc4_128 | des_cbc | '3des_ede_cbc'
@@ -121,115 +126,57 @@
<p><c>ssl_imp() = new | old - default is new.</c></p>
</section>
-
-<section>
- <title>SSL OPTION DESCRIPTIONS</title>
+
+ <section>
+ <title>SSL OPTION DESCRIPTIONS - COMMON for SERVER and CLIENT</title>
+
+ <p>Options described here are options that are have the same
+ meaning in the client and the server.
+ </p>
<taglist>
- <tag>{verify, verify_type()}</tag>
- <item> If <c>verify_none</c> is specified x509-certificate
- path validation errors at the client side
- will not automatically cause the connection to fail, as
- it will if the verify type is <c>verify_peer</c>. See also
- the option verify_fun.
- Servers only do the path validation if <c>verify_peer</c> is set to
- true, as it then will
- send a certificate request to
- the client (this message is not sent if the verify option is
- <c>verify_none</c>) and you may then also want to specify
- the option <c>fail_if_no_peer_cert</c>.
- </item>
- <tag>{fail_if_no_peer_cert, boolean()}</tag>
- <item>Used together with {verify, verify_peer} by a ssl server.
- If set to true,
- the server will fail if the client does not have a certificate
- to send, e.i sends a empty certificate, if set to false it will
- only fail if the client sends a invalid certificate (an empty
- certificate is considered valid).
- </item>
+ <tag>{cert, der_bin()}</tag>
+ <item> The DER encoded users certificate. If this option
+ is supplied it will override the certfile option.</item>
- <tag>{verify_fun, fun(ErrorList) -> boolean()}</tag>
- <item>Used by the ssl client to determine if
- x509-certificate path validations errors are acceptable or
- if the connection should fail. Defaults to:
-
-<code>
-fun(ErrorList) ->
- case lists:foldl(fun({bad_cert,unknown_ca}, Acc) ->
- Acc;
- (Other, Acc) ->
- [Other | Acc]
- end, [], ErrorList) of
- [] ->
- true;
- [_|_] ->
- false
- end
-end
-</code>
- I.e. by default if the only error found was that the CA-certificate
- holder was unknown this will be accepted.
-
- Possible errors in the error list are:
- {bad_cert, cert_expired}, {bad_cert, invalid_issuer},
- {bad_cert, invalid_signature}, {bad_cert, name_not_permitted},
- {bad_cert, unknown_ca},
- {bad_cert, cert_expired}, {bad_cert, invalid_issuer},
- {bad_cert, invalid_signature}, {bad_cert, name_not_permitted},
- {bad_cert, cert_revoked} (not implemented yet),
- {bad_cert, unknown_critical_extension} or {bad_cert, term()}
- </item>
-
+ <tag>{certfile, path()}</tag>
+ <item>Path to a file containing the user's certificate.</item>
- <tag>{validate_extensions_fun, fun()}</tag>
- <item>
- This options makes it possible to supply a fun to validate
- possible application specific certificate extensions
- during the certificat path validation. This option
- will be better documented onec the public_key API is more
- mature.
- </item>
+ <tag>{key, der_bin()}</tag>
+ <item> The DER encoded users private key. If this option
+ is supplied it will override the keyfile option.</item>
- <tag>{depth, integer()}</tag>
- <item>Specifies the maximum
- verification depth, i.e. how far in a chain of certificates the
- verification process can proceed before the verification is
- considered to fail. Peer certificate = 0, CA certificate = 1,
- higher level CA certificate = 2, etc. The value 2 thus means
- that a chain can at most contain peer cert, CA cert, next CA
- cert, and an additional CA cert. The default value is 1.
- </item>
-
- <tag>{certfile, path()}</tag>
- <item>Path to a file containing the
- user's certificate. Optional for clients but note
- that some servers requires that the client can certify
- itself. </item>
<tag>{keyfile, path()}</tag>
<item>Path to file containing user's
private PEM encoded key. As PEM-files may contain several
entries this option defaults to the same file as given by
certfile option.</item>
+
<tag>{password, string()}</tag>
<item>String containing the user's password.
Only used if the private keyfile is password protected.
</item>
+
+ <tag>{cacerts, [der_bin()]}</tag>
+ <item> The DER encoded trusted certificates. If this option
+ is supplied it will override the cacertfile option.</item>
+
<tag>{cacertfile, path()}</tag>
<item>Path to file containing PEM encoded
CA certificates (trusted certificates used for verifying a peer
certificate). May be omitted if you do not want to verify
the peer.</item>
- <tag>{dhfile, path()}</tag>
- <item>Path to file containing PEM encoded Diffie Hellman parameters,
- for the server to use if a cipher suite using Diffie Hellman key exchange
- is negotiated. If not specified hardcode parameters will be used.
- </item>
-
<tag>{ciphers, ciphers()}</tag>
- <item>The function <c>ciphers_suites/0</c> can
- be used to find all available ciphers.
+ <item>The cipher suites that should be supported. The function
+ <c>cipher_suites/0</c> can be used to find all available
+ ciphers. Additionally some anonymous cipher suites ({dh_anon,
+ rc4_128, md5}, {dh_anon, des_cbc, sha}, {dh_anon,
+ '3des_ede_cbc', sha}, {dh_anon, aes_128_cbc, sha}, {dh_anon,
+ aes_256_cbc, sha}) are supported for testing purposes and will
+ only work if explicitly enabled by this option and they are supported/enabled
+ by the peer also.
</item>
<tag>{ssl_imp, ssl_imp()}</tag>
@@ -237,13 +184,158 @@ end
new.
</item>
+ <tag>{secure_renegotiate, boolean()}</tag>
+ <item>Specifies if to reject renegotiation attempt that does
+ not live up to RFC 5746. By default secure_renegotiate is
+ set to false i.e. secure renegotiation will be used if possible
+ but it will fallback to unsecure renegotiation if the peer
+ does not support RFC 5746.
+ </item>
+
+ <tag>{depth, integer()}</tag>
+ <item>Specifies the maximum
+ verification depth, i.e. how far in a chain of certificates the
+ verification process can proceed before the verification is
+ considered to fail. Peer certificate = 0, CA certificate = 1,
+ higher level CA certificate = 2, etc. The value 2 thus means
+ that a chain can at most contain peer cert, CA cert, next CA
+ cert, and an additional CA cert. The default value is 1.
+ </item>
+
+ <tag>{verify_fun, {Verifyfun :: fun(), InitialUserState :: term()}}</tag>
+ <item>
+ <p>The verification fun should be defined as:</p>
+
+ <code>
+fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
+ {extension, #'Extension'{}}, InitialUserState :: term()) ->
+ {valid, UserState :: term()} | {valid_peer, UserState :: term()} |
+ {fail, Reason :: term()} | {unknown, UserState :: term()}.
+ </code>
+
+ <p>The verify fun will be called during the X509-path
+ validation when an error or an extension unknown to the ssl
+ application is encountered. Additionally it will be called
+ when a certificate is considered valid by the path validation
+ to allow access to each certificate in the path to the user
+ application. Note that the it will differentiate between
+ the peer certificate and CA certificates by using valid_peer
+ or valid as the second argument to the verify fun.
+ See
+ <seealso marker="public_key:application">public_key(3)</seealso>
+ for definition of #'OTPCertificate'{} and #'Extension'{}.</p>
+
+ <p>If the verify callback fun returns {fail, Reason}, the
+ verification process is immediately stopped and an alert is
+ sent to the peer and the TLS/SSL handshake is terminated. If
+ the verify callback fun returns {valid, UserState}, the
+ verification process is continued. If the verify callback fun
+ always returns {valid, UserState}, the TLS/SSL handshake will
+ not be terminated with respect to verification failures and
+ the connection will be established. If called with an
+ extension unknown to the user application the return value
+ {unknown, UserState} should be used.</p>
+
+ <p>The default verify_fun option in verify_peer mode:</p>
+
+ <code>
+{fun(_,{bad_cert, _} = Reason, _) ->
+ {fail, Reason};
+ (_,{extension, _}, UserState) ->
+ {unknown, UserState};
+ (_, valid, UserState) ->
+ {valid, UserState};
+ (_, valid_peer, UserState) ->
+ {valid, UserState}
+ end, []}
+ </code>
+
+ <p>The default verify_fun option in verify_none mode:</p>
+
+ <code>
+{fun(_,{bad_cert, _}, UserState) ->
+ {valid, UserState};
+ (_,{extension, _}, UserState) ->
+ {unknown, UserState};
+ (_, valid, UserState) ->
+ {valid, UserState};
+ (_, valid_peer, UserState) ->
+ {valid, UserState}
+ end, []}
+ </code>
+
+<p>Possible path validation errors: </p>
+
+<p> {bad_cert, cert_expired}, {bad_cert, invalid_issuer}, {bad_cert, invalid_signature}, {bad_cert, unknown_ca}, {bad_cert, name_not_permitted}, {bad_cert, missing_basic_constraint}, {bad_cert, invalid_key_usage}</p>
+ </item>
+
+ </taglist>
+
+ </section>
+
+ <section>
+ <title>SSL OPTION DESCRIPTIONS - CLIENT SIDE</title>
+
+ <p>Options described here are client specific or has a slightly different
+ meaning in the client than in the server.</p>
+
+ <taglist>
+ <tag>{verify, verify_type()}</tag>
+ <item> In verify_none mode the default behavior will be to
+ allow all x509-path validation errors. See also the verify_fun
+ option.
+ </item>
<tag>{reuse_sessions, boolean()}</tag>
- <item>Specifies if ssl sessions should be reused
- when possible.
+ <item>Specifies if client should try to reuse sessions
+ when possible.
</item>
- <tag>{reuse_session, fun(SuggestedSessionId,
- PeerCert, Compression, CipherSuite) -> boolean()}</tag>
+ </taglist>
+ </section>
+
+ <section>
+ <title>SSL OPTION DESCRIPTIONS - SERVER SIDE</title>
+
+ <p>Options described here are server specific or has a slightly different
+ meaning in the server than in the client.</p>
+
+ <taglist>
+
+ <tag>{dh, der_bin()}</tag>
+ <item>The DER encoded Diffie Hellman parameters. If this option
+ is supplied it will override the dhfile option.
+ </item>
+
+ <tag>{dhfile, path()}</tag>
+ <item>Path to file containing PEM encoded Diffie Hellman parameters,
+ for the server to use if a cipher suite using Diffie Hellman key exchange
+ is negotiated. If not specified default parameters will be used.
+ </item>
+
+ <tag>{verify, verify_type()}</tag>
+ <item>Servers only do the x509-path validation in verify_peer
+ mode, as it then will send a certificate request to the client
+ (this message is not sent if the verify option is verify_none)
+ and you may then also want to specify the option
+ fail_if_no_peer_cert.
+ </item>
+
+ <tag>{fail_if_no_peer_cert, boolean()}</tag>
+ <item>Used together with {verify, verify_peer} by a ssl server.
+ If set to true, the server will fail if the client does not have
+ a certificate to send, i.e. sends a empty certificate, if set to
+ false it will only fail if the client sends a invalid
+ certificate (an empty certificate is considered valid).
+ </item>
+
+ <tag>{reuse_sessions, boolean()}</tag>
+ <item>Specifies if the server should agree to reuse sessions
+ when the clients request to do so. See also the reuse_session
+ option.
+ </item>
+
+ <tag>{reuse_session, fun(SuggestedSessionId,
+ PeerCert, Compression, CipherSuite) -> boolean()}</tag>
<item>Enables the ssl server to have a local policy
for deciding if a session should be reused or not,
only meaning full if <c>reuse_sessions</c> is set to true.
@@ -252,14 +344,6 @@ end
and CipherSuite of type ciphersuite().
</item>
- <tag>{secure_renegotiate, boolean()}</tag>
- <item>Specifies if to reject renegotiation attempt that does
- not live up to RFC 5746. By default secure_renegotiate is
- set to false e.i. secure renegotiation will be used if possible
- but it will fallback to unsecure renegotiation if the peer
- does not support RFC 5746.
- </item>
-
</taglist>
</section>
@@ -316,7 +400,7 @@ end
<v>Reason = term()</v>
</type>
<desc> <p>Upgrades a gen_tcp, or equivalent,
- connected socket to a ssl socket e.i performs the
+ connected socket to a ssl socket i.e. performs the
client-side ssl handshake.</p>
</desc>
</func>
@@ -559,12 +643,12 @@ end
</type>
<desc>
<p> Upgrades a gen_tcp, or
- equivalent, socket to a ssl socket e.i performs the
+ equivalent, socket to a ssl socket i.e. performs the
ssl server-side handshake.</p>
- <p><note>Note that the listen socket should be in {active, false} mode
+ <p><warning>Note that the listen socket should be in {active, false} mode
before telling the client that the server is ready to upgrade
and calling this function, otherwise the upgrade may
- or may not succeed depending on timing.</note></p>
+ or may not succeed depending on timing.</warning></p>
</desc>
</func>
diff --git a/lib/ssl/doc/src/ssl_distribution.xml b/lib/ssl/doc/src/ssl_distribution.xml
index 4067fb8a22..7bcc12eb5f 100644
--- a/lib/ssl/doc/src/ssl_distribution.xml
+++ b/lib/ssl/doc/src/ssl_distribution.xml
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE chapter SYSTEM "chapter.dtd">
<chapter>
<header>
<copyright>
- <year>2000</year><year>2009</year>
+ <year>2000</year><year>2010</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -36,7 +36,7 @@
<note><p>Note this
documentation is written for the old ssl implementation and
- will be updated for the new one once this functionallity is
+ will be updated for the new one once this functionality is
supported by the new implementation.</p></note>
</p>
@@ -55,7 +55,7 @@
all participating Erlang nodes in a distributed system must use
this distribution module.</p>
<p>The security depends on how the connections are set up, one can
- use key files or certificates to just get a crypted
+ use key files or certificates to just get a encrypted
connection. One can also make the SSL package verify the
certificates of other nodes to get additional security.
Cookies are however always used as they can be used to
@@ -179,7 +179,7 @@ Eshell V5.0 (abort with ^G)
<c>certfile</c> can (and usually needs to) be specified as
<c>client_certfile</c> and <c>server_certfile</c>. The
<c>client_certfile</c> is used when the distribution initiates a
- connection to another node and the <c>server_cerfile</c> is used
+ connection to another node and the <c>server_certfile</c> is used
when accepting a connection from a remote node. </p>
<p>The command line argument for specifying the SSL options is named
<c>-ssl_dist_opt</c> and should be followed by an even number of
diff --git a/lib/ssl/doc/src/ssl_protocol.xml b/lib/ssl/doc/src/ssl_protocol.xml
index 726b9a4eeb..6936408881 100644
--- a/lib/ssl/doc/src/ssl_protocol.xml
+++ b/lib/ssl/doc/src/ssl_protocol.xml
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE chapter SYSTEM "chapter.dtd">
<chapter>
<header>
<copyright>
- <year>2003</year><year>2009</year>
+ <year>2003</year><year>2010</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -44,7 +44,7 @@
<section>
<title>Security overview</title>
- <p>To achive authentication and privacy the client and server will
+ <p>To achieve authentication and privacy the client and server will
perform a TLS Handshake procedure before transmitting or receiving
any data. During the handshake they agree on a protocol version and
cryptographic algorithms, they generate shared secrets using public
@@ -56,7 +56,7 @@
<title>Data Privacy and Integrity</title>
<p>A <em>symmetric key</em> algorithm has one key only. The key is
- used for both encryption and decryption. These algoritms are fast
+ used for both encryption and decryption. These algorithms are fast
compared to public key algorithms (using two keys, a public and a
private one) and are therefore typically used for encrypting bulk
data.
@@ -66,7 +66,7 @@
for each connection and are based on a secret negotiated
in the TLS handshake. </p>
- <p>The TLS handsake protocol and data transfer is run on top of
+ <p>The TLS handshake protocol and data transfer is run on top of
the TLS Record Protocol that uses a keyed-hash MAC (Message
Authenticity Code), or HMAC, to protect the message's data
integrity. From the TLS RFC "A Message Authentication Code is a
@@ -85,7 +85,7 @@
with the private key of the issuer of the certificate. A chain
of trust is build by having the issuer in its turn being
certified by an other certificate and so on until you reach the
- so called root certificate that is self signed e.i. issued
+ so called root certificate that is self signed i.e. issued
by itself.</p>
<p>Certificates are issued by <em>certification
diff --git a/lib/ssl/doc/src/ssl_session_cache_api.xml b/lib/ssl/doc/src/ssl_session_cache_api.xml
index 7b70c6cf34..e0b07961fb 100644
--- a/lib/ssl/doc/src/ssl_session_cache_api.xml
+++ b/lib/ssl/doc/src/ssl_session_cache_api.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE erlref SYSTEM "erlref.dtd">
<erlref>
@@ -25,7 +25,7 @@
</header>
<module>ssl_session_cache_api</module>
<modulesummary>Defines the API for the TLS session cache so
- that the datastorge scheme can be replaced by
+ that the data storage scheme can be replaced by
defining a new callback module implementing this API.</modulesummary>
<section>
@@ -56,7 +56,7 @@
<v> Key = key()</v>
</type>
<desc>
- <p> Delets a cache entry. Will only be called from the cache
+ <p> Deletes a cache entry. Will only be called from the cache
handling process.
</p>
</desc>
@@ -85,10 +85,10 @@
<v></v>
</type>
<desc>
- <p>Performes possible initializations of the cache and returns
+ <p>Performs possible initializations of the cache and returns
a reference to it that will be used as parameter to the other
api functions. Will be called by the cache handling processes
- init function, hence puting the same requierments on it as
+ init function, hence putting the same requirements on it as
a normal process init function.
</p>
</desc>
@@ -96,16 +96,16 @@
<func>
<name>lookup(Cache, Key) -> Entry</name>
- <fsummary> Looks up a cach entry.</fsummary>
+ <fsummary> Looks up a cache entry.</fsummary>
<type>
<v> Cache = cache_ref()</v>
<v> Key = key()</v>
<v> Entry = session() | undefined </v>
</type>
<desc>
- <p>Looks up a cach entry. Should be callable from any
- process.
- </p>
+ <p>Looks up a cache entry. Should be callable from any
+ process.
+ </p>
</desc>
</func>
@@ -127,7 +127,7 @@
<func>
<name>terminate(Cache) -> _</name>
<fsummary>Called by the process that handles the cache when it
- is aboute to terminat.</fsummary>
+ is about to terminate.</fsummary>
<type>
<v>Cache = term() - as returned by init/0</v>
</type>
diff --git a/lib/ssl/examples/certs/Makefile b/lib/ssl/examples/certs/Makefile
index 121fcc6950..b811b461dc 100644
--- a/lib/ssl/examples/certs/Makefile
+++ b/lib/ssl/examples/certs/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2003-2009. All Rights Reserved.
+# Copyright Ericsson AB 2003-2010. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -21,4 +21,41 @@
# Invoke with GNU make or clearmake -C gnu.
#
-include $(ERL_TOP)/make/run_make.mk
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../../vsn.mk
+VSN=$(SSL_VSN)
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/ssl-$(VSN)
+
+TARGET_FILES=
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+debug opt: $(TARGET_FILES)
+
+clean:
+ rm -fr $(TARGET_FILES) *~ *.beam
+
+docs:
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_spec: opt
+ $(INSTALL_DIR) $(RELSYSDIR)/examples/certs
+ tar cf - etc | \
+ (cd $(RELSYSDIR)/examples/certs; tar xf -)
+ chmod -f -R ug+rw $(RELSYSDIR)/examples
+release_docs_spec:
diff --git a/lib/ssl/examples/certs/Makefile.in b/lib/ssl/examples/certs/Makefile.in
deleted file mode 100644
index 4ea7aaf6dc..0000000000
--- a/lib/ssl/examples/certs/Makefile.in
+++ /dev/null
@@ -1,80 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2003-2009. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-#
-
-#
-
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-include ../../vsn.mk
-VSN=$(SSL_VSN)
-
-RELSYSDIR = $(RELEASE_PATH)/lib/ssl-$(VSN)
-
-EBIN = ebin
-ETC = etc
-SRC = src
-
-OPENSSL_CMD = @OPENSSL_CMD@
-
-# We are generating more files than in the following list, but we take
-# there existence as successful execution of make rules
-
-PEMS = cacerts.pem cert.pem key.pem
-
-PEMFILES = $(PEMS:%=$(ETC)/client/%) $(PEMS:%=$(ETC)/server/%)
-
-debug opt: $(PEMFILES)
-
-$(PEMFILES): done
-
-done: $(EBIN)/make_certs.beam
- erl -noinput -pa $(EBIN) -run make_certs all $(OPENSSL_CMD) \
- -s erlang halt
- echo >done
-
-$(EBIN)/make_certs.beam: $(SRC)/make_certs.erl
- cd src; erlc -W -o ../$(EBIN) make_certs.erl
-
-clean:
- rm -fr $(EBIN)/* $(SRC)/*~ $(SRC)/*.beam $(ETC) done \
- stderr.txt erl_crash.dump *~
-
-docs:
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/examples/certs
- tar cf - Makefile ebin etc rnd src | \
- (cd $(RELSYSDIR)/examples/certs; tar xf -)
- chmod -f -R ug+rw $(RELSYSDIR)/examples
-
-release_docs_spec:
-
-
-
-
-
-
-
-
diff --git a/lib/ssl/examples/certs/ebin/.gitignore b/lib/ssl/examples/certs/ebin/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/ssl/examples/certs/ebin/.gitignore
+++ /dev/null
diff --git a/lib/ssl/examples/certs/etc/client/cacerts.pem b/lib/ssl/examples/certs/etc/client/cacerts.pem
new file mode 100644
index 0000000000..cb19d3d41e
--- /dev/null
+++ b/lib/ssl/examples/certs/etc/client/cacerts.pem
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+MIICizCCAfSgAwIBAgIFdMMs9fEwDQYJKoZIhvcNAQEFBQAwfTERMA8GA1UEAxMI
+ZXJsYW5nQ0ExIDAeBgkqhkiG9w0BCQEWEXRlc3RlckBlcmxhbmcub3JnMRIwEAYD
+VQQHEwlTdG9ja2hvbG0xCzAJBgNVBAYTAlNFMQ8wDQYDVQQKEwZlcmxhbmcxFDAS
+BgNVBAsTC3Rlc3RpbmcgZGVwMCIYDzIwMTAwOTAxMDAwMDAwWhgPMjAyNTA4Mjgw
+MDAwMDBaMH0xETAPBgNVBAMTCGVybGFuZ0NBMSAwHgYJKoZIhvcNAQkBFhF0ZXN0
+ZXJAZXJsYW5nLm9yZzESMBAGA1UEBxMJU3RvY2tob2xtMQswCQYDVQQGEwJTRTEP
+MA0GA1UEChMGZXJsYW5nMRQwEgYDVQQLEwt0ZXN0aW5nIGRlcDCBnzANBgkqhkiG
+9w0BAQEFAAOBjQAwgYkCgYEAgmHw2xApZqdzZOOPTzwHr1hRYd1OqbLOsXbAq6kJ
+Kuu+qe5jAlMF3vnUhiHomuZeNZVJe3SP+JfBt3BHMjm2CLChCuNgfctKURMlEc/L
+xo8fO1Jk9MD5mbG2Utx3m3gM6Liwt9fHVABlCTyB6/jXrK1tYpEG5CrwUXyy8Htl
+jHECAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAl
+0tMEXWPgzXTpDuNmuKh6aGq9CuExUuEXXQQWPThzEuluA3aHFmObziQlMY1+KeO1
+AL0kpx0Yhvju/rfAJ+OF6MMni6hJoKlYTVml+fCY89A3nmY1rJHJavjHp0OIPGxh
+4Sr+EcjROkqe8jE0DmbwmM6lzpwSJscxte+V6HvGRw==
+-----END CERTIFICATE-----
+
+-----BEGIN CERTIFICATE-----
+MIICiDCCAfGgAwIBAgIFSHyFNTEwDQYJKoZIhvcNAQEFBQAwfTERMA8GA1UEAxMI
+ZXJsYW5nQ0ExIDAeBgkqhkiG9w0BCQEWEXRlc3RlckBlcmxhbmcub3JnMRIwEAYD
+VQQHEwlTdG9ja2hvbG0xCzAJBgNVBAYTAlNFMQ8wDQYDVQQKEwZlcmxhbmcxFDAS
+BgNVBAsTC3Rlc3RpbmcgZGVwMCIYDzIwMTAwOTAxMDAwMDAwWhgPMjAyNTA4Mjgw
+MDAwMDBaMHoxDjAMBgNVBAMTBW90cENBMSAwHgYJKoZIhvcNAQkBFhF0ZXN0ZXJA
+ZXJsYW5nLm9yZzESMBAGA1UEBxMJU3RvY2tob2xtMQswCQYDVQQGEwJTRTEPMA0G
+A1UEChMGZXJsYW5nMRQwEgYDVQQLEwt0ZXN0aW5nIGRlcDCBnzANBgkqhkiG9w0B
+AQEFAAOBjQAwgYkCgYEAjEt9iy365+mTialKDKb3l2QPg71yavJA1ZC6aGC14X7x
+KCm1FhUYsVKOlWjmC1VYJiCS01gvKqMXiogreHJGM93E+URlKkOm9kmOWQwLfFb8
+JLzafPi3/8TUdjl8UuIDHyPsoQiM2ZBDUVWezfl+CBsTYFO3U4Lqf9OKbCxTF78C
+AwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAv6vHw
+wK3MvxzlhDJIx7rUasOYJDZJyOt71KdOKeA7+ocbvDIblmV7sTbe3oQNqbSATZ6H
+RUqHZdPhKIZ9wjEBSKdBTL8rc0TvbztMvd+i0rkTCL/bspQYchA2zCcjgkWqpaN4
+OhOjQR1+9/ntmaU/r5Ca7KmrXEf5XSQIGLSMag==
+-----END CERTIFICATE-----
+
diff --git a/lib/ssl/examples/certs/etc/client/cert.pem b/lib/ssl/examples/certs/etc/client/cert.pem
new file mode 100644
index 0000000000..a2f53aaf82
--- /dev/null
+++ b/lib/ssl/examples/certs/etc/client/cert.pem
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIIChzCCAfCgAwIBAgIGAIsapa8BMA0GCSqGSIb3DQEBBQUAMHoxDjAMBgNVBAMT
+BW90cENBMSAwHgYJKoZIhvcNAQkBFhF0ZXN0ZXJAZXJsYW5nLm9yZzESMBAGA1UE
+BxMJU3RvY2tob2xtMQswCQYDVQQGEwJTRTEPMA0GA1UEChMGZXJsYW5nMRQwEgYD
+VQQLEwt0ZXN0aW5nIGRlcDAiGA8yMDEwMDkwMTAwMDAwMFoYDzIwMjUwODI4MDAw
+MDAwWjB7MQ8wDQYDVQQDEwZjbGllbnQxIDAeBgkqhkiG9w0BCQEWEXRlc3RlckBl
+cmxhbmcub3JnMRIwEAYDVQQHEwlTdG9ja2hvbG0xCzAJBgNVBAYTAlNFMQ8wDQYD
+VQQKEwZlcmxhbmcxFDASBgNVBAsTC3Rlc3RpbmcgZGVwMIGfMA0GCSqGSIb3DQEB
+AQUAA4GNADCBiQKBgQCTFBPkOO98fDY3j6MIxIGKp+rampfIay50Lx4+EnCnRSSV
+wC+n0VVmP7V5SGFJpuXJzN0hvqPUWOOjiMTNlNRaGy0pqu2oMXWAPLOxHWL1wT53
+h2Zr3FUNU/N0Rvnkttse1KZJ9uYCLKUiuXXsv2rR62nH3OhRIiBHSAcSv0NRWwID
+AQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAG8t6f1A
+PF7xayGxtUpG2r6W5ETylC3ZIKPS2kfJk9aYi7AZNTp7/xTU6SgqvFBN8aBPzxCD
+4jHrSNC8DSb4X1x9uimarb6qdZDHEdij+DRAd2eygJHZxEf7+8B4Fx34thQeU9hZ
+S1Izke5AlsyFMkvB7h0anE4k9BfuU70vl6v5
+-----END CERTIFICATE-----
+
diff --git a/lib/ssl/examples/certs/etc/client/key.pem b/lib/ssl/examples/certs/etc/client/key.pem
new file mode 100644
index 0000000000..4d55b08f4c
--- /dev/null
+++ b/lib/ssl/examples/certs/etc/client/key.pem
@@ -0,0 +1,16 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQCTFBPkOO98fDY3j6MIxIGKp+rampfIay50Lx4+EnCnRSSVwC+n
+0VVmP7V5SGFJpuXJzN0hvqPUWOOjiMTNlNRaGy0pqu2oMXWAPLOxHWL1wT53h2Zr
+3FUNU/N0Rvnkttse1KZJ9uYCLKUiuXXsv2rR62nH3OhRIiBHSAcSv0NRWwIDAQAB
+AoGACdIVYe/LTeydUihtInC8lZ2QuPgJmoBNocRjqJFipEihoL4scHAx25n1bBvB
+I0HZphffzBkGp28oBAtl2LRPWXqu527unc/RWRfLMqSK1xNSq1DxD1a30zkrZPna
+QiV65vEJuNSJTtlDy/Zqc/BVZXCpxWlzYQedZgkmf0Qse8ECQQCmaz02Yur8zC9f
+eSQKU5OSzGw3bSIumEzziCfHdTheK6MEoccf5TCAyLXhZwA7QlKja4tFXfeyVxws
+/LlnUJN9AkEA4j+xnOeYUyGKXL5i+BAbnqpI4MzPiq+IoCYkaRlD/wAws24r5HNI
+ZQmEHWqD/NNzOf/A2XuyLtMiTGJPW/DftwJBAKKpJP6Ytuh6xz8BUCnLwO12Y7vV
+LtjuQiCzD3aUa5EYA9HOMqxJPxxRkf0LyR0i2VUkE8+sZiPpov+R0cJa7p0CQQCj
+40GUiArGRSiF7/+e84QeVfl+pb29F1QftiFv5DZmFEwy3Z572KpbTh5edJbxYHY6
+UDHxGHJFCvnwXNJhpkVXAkBJqfEfiMJ3Q/E5Gpf3sQizacouW92iiN8ojlF1oB80
+t34RysJH7SgI3gdMhTribCo2UUaV0StjR6yodPN+TB2J
+-----END RSA PRIVATE KEY-----
+
diff --git a/lib/ssl/examples/certs/etc/erlangCA/cert.pem b/lib/ssl/examples/certs/etc/erlangCA/cert.pem
new file mode 100644
index 0000000000..c4386494dc
--- /dev/null
+++ b/lib/ssl/examples/certs/etc/erlangCA/cert.pem
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICizCCAfSgAwIBAgIFdMMs9fEwDQYJKoZIhvcNAQEFBQAwfTERMA8GA1UEAxMI
+ZXJsYW5nQ0ExIDAeBgkqhkiG9w0BCQEWEXRlc3RlckBlcmxhbmcub3JnMRIwEAYD
+VQQHEwlTdG9ja2hvbG0xCzAJBgNVBAYTAlNFMQ8wDQYDVQQKEwZlcmxhbmcxFDAS
+BgNVBAsTC3Rlc3RpbmcgZGVwMCIYDzIwMTAwOTAxMDAwMDAwWhgPMjAyNTA4Mjgw
+MDAwMDBaMH0xETAPBgNVBAMTCGVybGFuZ0NBMSAwHgYJKoZIhvcNAQkBFhF0ZXN0
+ZXJAZXJsYW5nLm9yZzESMBAGA1UEBxMJU3RvY2tob2xtMQswCQYDVQQGEwJTRTEP
+MA0GA1UEChMGZXJsYW5nMRQwEgYDVQQLEwt0ZXN0aW5nIGRlcDCBnzANBgkqhkiG
+9w0BAQEFAAOBjQAwgYkCgYEAgmHw2xApZqdzZOOPTzwHr1hRYd1OqbLOsXbAq6kJ
+Kuu+qe5jAlMF3vnUhiHomuZeNZVJe3SP+JfBt3BHMjm2CLChCuNgfctKURMlEc/L
+xo8fO1Jk9MD5mbG2Utx3m3gM6Liwt9fHVABlCTyB6/jXrK1tYpEG5CrwUXyy8Htl
+jHECAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAl
+0tMEXWPgzXTpDuNmuKh6aGq9CuExUuEXXQQWPThzEuluA3aHFmObziQlMY1+KeO1
+AL0kpx0Yhvju/rfAJ+OF6MMni6hJoKlYTVml+fCY89A3nmY1rJHJavjHp0OIPGxh
+4Sr+EcjROkqe8jE0DmbwmM6lzpwSJscxte+V6HvGRw==
+-----END CERTIFICATE-----
+
diff --git a/lib/ssl/examples/certs/etc/otpCA/cert.pem b/lib/ssl/examples/certs/etc/otpCA/cert.pem
new file mode 100644
index 0000000000..8610621695
--- /dev/null
+++ b/lib/ssl/examples/certs/etc/otpCA/cert.pem
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICiDCCAfGgAwIBAgIFSHyFNTEwDQYJKoZIhvcNAQEFBQAwfTERMA8GA1UEAxMI
+ZXJsYW5nQ0ExIDAeBgkqhkiG9w0BCQEWEXRlc3RlckBlcmxhbmcub3JnMRIwEAYD
+VQQHEwlTdG9ja2hvbG0xCzAJBgNVBAYTAlNFMQ8wDQYDVQQKEwZlcmxhbmcxFDAS
+BgNVBAsTC3Rlc3RpbmcgZGVwMCIYDzIwMTAwOTAxMDAwMDAwWhgPMjAyNTA4Mjgw
+MDAwMDBaMHoxDjAMBgNVBAMTBW90cENBMSAwHgYJKoZIhvcNAQkBFhF0ZXN0ZXJA
+ZXJsYW5nLm9yZzESMBAGA1UEBxMJU3RvY2tob2xtMQswCQYDVQQGEwJTRTEPMA0G
+A1UEChMGZXJsYW5nMRQwEgYDVQQLEwt0ZXN0aW5nIGRlcDCBnzANBgkqhkiG9w0B
+AQEFAAOBjQAwgYkCgYEAjEt9iy365+mTialKDKb3l2QPg71yavJA1ZC6aGC14X7x
+KCm1FhUYsVKOlWjmC1VYJiCS01gvKqMXiogreHJGM93E+URlKkOm9kmOWQwLfFb8
+JLzafPi3/8TUdjl8UuIDHyPsoQiM2ZBDUVWezfl+CBsTYFO3U4Lqf9OKbCxTF78C
+AwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAv6vHw
+wK3MvxzlhDJIx7rUasOYJDZJyOt71KdOKeA7+ocbvDIblmV7sTbe3oQNqbSATZ6H
+RUqHZdPhKIZ9wjEBSKdBTL8rc0TvbztMvd+i0rkTCL/bspQYchA2zCcjgkWqpaN4
+OhOjQR1+9/ntmaU/r5Ca7KmrXEf5XSQIGLSMag==
+-----END CERTIFICATE-----
+
diff --git a/lib/ssl/examples/certs/etc/server/cacerts.pem b/lib/ssl/examples/certs/etc/server/cacerts.pem
new file mode 100644
index 0000000000..cb19d3d41e
--- /dev/null
+++ b/lib/ssl/examples/certs/etc/server/cacerts.pem
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+MIICizCCAfSgAwIBAgIFdMMs9fEwDQYJKoZIhvcNAQEFBQAwfTERMA8GA1UEAxMI
+ZXJsYW5nQ0ExIDAeBgkqhkiG9w0BCQEWEXRlc3RlckBlcmxhbmcub3JnMRIwEAYD
+VQQHEwlTdG9ja2hvbG0xCzAJBgNVBAYTAlNFMQ8wDQYDVQQKEwZlcmxhbmcxFDAS
+BgNVBAsTC3Rlc3RpbmcgZGVwMCIYDzIwMTAwOTAxMDAwMDAwWhgPMjAyNTA4Mjgw
+MDAwMDBaMH0xETAPBgNVBAMTCGVybGFuZ0NBMSAwHgYJKoZIhvcNAQkBFhF0ZXN0
+ZXJAZXJsYW5nLm9yZzESMBAGA1UEBxMJU3RvY2tob2xtMQswCQYDVQQGEwJTRTEP
+MA0GA1UEChMGZXJsYW5nMRQwEgYDVQQLEwt0ZXN0aW5nIGRlcDCBnzANBgkqhkiG
+9w0BAQEFAAOBjQAwgYkCgYEAgmHw2xApZqdzZOOPTzwHr1hRYd1OqbLOsXbAq6kJ
+Kuu+qe5jAlMF3vnUhiHomuZeNZVJe3SP+JfBt3BHMjm2CLChCuNgfctKURMlEc/L
+xo8fO1Jk9MD5mbG2Utx3m3gM6Liwt9fHVABlCTyB6/jXrK1tYpEG5CrwUXyy8Htl
+jHECAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAl
+0tMEXWPgzXTpDuNmuKh6aGq9CuExUuEXXQQWPThzEuluA3aHFmObziQlMY1+KeO1
+AL0kpx0Yhvju/rfAJ+OF6MMni6hJoKlYTVml+fCY89A3nmY1rJHJavjHp0OIPGxh
+4Sr+EcjROkqe8jE0DmbwmM6lzpwSJscxte+V6HvGRw==
+-----END CERTIFICATE-----
+
+-----BEGIN CERTIFICATE-----
+MIICiDCCAfGgAwIBAgIFSHyFNTEwDQYJKoZIhvcNAQEFBQAwfTERMA8GA1UEAxMI
+ZXJsYW5nQ0ExIDAeBgkqhkiG9w0BCQEWEXRlc3RlckBlcmxhbmcub3JnMRIwEAYD
+VQQHEwlTdG9ja2hvbG0xCzAJBgNVBAYTAlNFMQ8wDQYDVQQKEwZlcmxhbmcxFDAS
+BgNVBAsTC3Rlc3RpbmcgZGVwMCIYDzIwMTAwOTAxMDAwMDAwWhgPMjAyNTA4Mjgw
+MDAwMDBaMHoxDjAMBgNVBAMTBW90cENBMSAwHgYJKoZIhvcNAQkBFhF0ZXN0ZXJA
+ZXJsYW5nLm9yZzESMBAGA1UEBxMJU3RvY2tob2xtMQswCQYDVQQGEwJTRTEPMA0G
+A1UEChMGZXJsYW5nMRQwEgYDVQQLEwt0ZXN0aW5nIGRlcDCBnzANBgkqhkiG9w0B
+AQEFAAOBjQAwgYkCgYEAjEt9iy365+mTialKDKb3l2QPg71yavJA1ZC6aGC14X7x
+KCm1FhUYsVKOlWjmC1VYJiCS01gvKqMXiogreHJGM93E+URlKkOm9kmOWQwLfFb8
+JLzafPi3/8TUdjl8UuIDHyPsoQiM2ZBDUVWezfl+CBsTYFO3U4Lqf9OKbCxTF78C
+AwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAv6vHw
+wK3MvxzlhDJIx7rUasOYJDZJyOt71KdOKeA7+ocbvDIblmV7sTbe3oQNqbSATZ6H
+RUqHZdPhKIZ9wjEBSKdBTL8rc0TvbztMvd+i0rkTCL/bspQYchA2zCcjgkWqpaN4
+OhOjQR1+9/ntmaU/r5Ca7KmrXEf5XSQIGLSMag==
+-----END CERTIFICATE-----
+
diff --git a/lib/ssl/examples/certs/etc/server/cert.pem b/lib/ssl/examples/certs/etc/server/cert.pem
new file mode 100644
index 0000000000..f26adb7f5c
--- /dev/null
+++ b/lib/ssl/examples/certs/etc/server/cert.pem
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIIChzCCAfCgAwIBAgIGANUxXM9BMA0GCSqGSIb3DQEBBQUAMHoxDjAMBgNVBAMT
+BW90cENBMSAwHgYJKoZIhvcNAQkBFhF0ZXN0ZXJAZXJsYW5nLm9yZzESMBAGA1UE
+BxMJU3RvY2tob2xtMQswCQYDVQQGEwJTRTEPMA0GA1UEChMGZXJsYW5nMRQwEgYD
+VQQLEwt0ZXN0aW5nIGRlcDAiGA8yMDEwMDkwMTAwMDAwMFoYDzIwMjUwODI4MDAw
+MDAwWjB7MQ8wDQYDVQQDEwZzZXJ2ZXIxIDAeBgkqhkiG9w0BCQEWEXRlc3RlckBl
+cmxhbmcub3JnMRIwEAYDVQQHEwlTdG9ja2hvbG0xCzAJBgNVBAYTAlNFMQ8wDQYD
+VQQKEwZlcmxhbmcxFDASBgNVBAsTC3Rlc3RpbmcgZGVwMIGfMA0GCSqGSIb3DQEB
+AQUAA4GNADCBiQKBgQCf4Htxr99lLs5W8QQw7jdakqyAkIjOW4aqH8sr4va4SvZ9
+Adq67k8jMHefCVZo+F8x4cwsBgB4aWzFIGBnvFTi6YsH27XW7f9O9IPCej8fdhRZ
+4UAtNHa253buOWpDGla2JmIdkmfFvXFJycMIKbG5tYilVXoWKBMKmCwWaXz0nQID
+AQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAGF5Pfwk
+QDdwJup/mVITPxbBls4Yl7anDooUQsq8066lA1g54H/PRfXscGkyCFGh1ifXvf1L
+psMRoBAdDHL/wSJplk3rRavkC94eBgnTFZmfKL6844g1j53yameiYL8IEVExYMBg
+/XGyc0qwq57WT8B/K4aElrvlBlQ0wF3wN54M
+-----END CERTIFICATE-----
+
diff --git a/lib/ssl/examples/certs/etc/server/key.pem b/lib/ssl/examples/certs/etc/server/key.pem
new file mode 100644
index 0000000000..c1392ca557
--- /dev/null
+++ b/lib/ssl/examples/certs/etc/server/key.pem
@@ -0,0 +1,16 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQCf4Htxr99lLs5W8QQw7jdakqyAkIjOW4aqH8sr4va4SvZ9Adq6
+7k8jMHefCVZo+F8x4cwsBgB4aWzFIGBnvFTi6YsH27XW7f9O9IPCej8fdhRZ4UAt
+NHa253buOWpDGla2JmIdkmfFvXFJycMIKbG5tYilVXoWKBMKmCwWaXz0nQIDAQAB
+AoGAQIlma0r6W6bcRj4+Wd4fXCFvHuq5Psu1fYEeC5Yvz8761xVjjSfbrDHJZ9pm
+FjOEgedK+s5lbDXqYVyjbdyZSugStBRocSmbG8SQHcAsxR2ZIkNzX2hYzB+lslWo
+T3YJojDyB134O7XJznCu+ZFXP86jyJ1JT6k6a+OIHcwnJ+ECQQDYn57dY4Px3mEd
+VBLStN3YkRF5oFyT+xk7IaKeLLB6n4gCnoVbBoHut7PFbPYPzoNzEwPk3MQKDIHb
+Kig3S5CpAkEAvPA1VmoJWAlN6kUi+F2L8HXEArzE8x7vwdsslrwMKUe4dFS+ZC/7
+5iDOaxcZ7TYkCgwzBt341++DCgP6j3fY1QJBALB6AcOcwi52m6l4B8mu3ZkEPjdX
+BHTuONTqhv/TqoaLlxODL2NDvvDKqeMp7KBd/srt79swW2lQXS4+fvrlTdkCQQCm
+zxj4O1QWkthkfje6ubSkTwUIOatUzrp1F9GNH2dJRtX2dx9FCwxGCC7WY6XzRXqa
+GF0wsedSllbGD+82nWQlAkAicMGqCqRq4hKR/cVmFatOqKVWCVkx6OFF2FhuiI5Z
+h5eIOPGCt8dVRs1P9DNSld/D98Sfm65m85z8BtXovvYV
+-----END RSA PRIVATE KEY-----
+
diff --git a/lib/ssl/examples/certs/rnd/RAND b/lib/ssl/examples/certs/rnd/RAND
deleted file mode 100644
index 70997bd01f..0000000000
--- a/lib/ssl/examples/certs/rnd/RAND
+++ /dev/null
Binary files differ
diff --git a/lib/ssl/examples/certs/src/make_certs.erl b/lib/ssl/examples/certs/src/make_certs.erl
index c374836568..fe267bed28 100644
--- a/lib/ssl/examples/certs/src/make_certs.erl
+++ b/lib/ssl/examples/certs/src/make_certs.erl
@@ -1,261 +1,48 @@
-%% The purpose of this module is to create example certificates for
-%% testing.
-%% Run it as:
-%%
-%% erl -noinput -run make_certs all "/path/to/openssl" -s erlang halt
-%%
+%% The purpose of this module is to log how the example certs where created,
+%% it requires erl_make_certs found in the test directory.
-module(make_certs).
--export([all/0, all/1]).
-
--record(dn, {commonName,
- organizationalUnitName = "Erlang OTP",
- organizationName = "Ericsson AB",
- localityName = "Stockholm",
- countryName = "SE",
- emailAddress = "[email protected]"}).
+-export([all/0]).
all() ->
- all(["openssl"]).
-
-all([OpenSSLCmd]) ->
- Root = filename:dirname(filename:dirname((code:which(?MODULE)))),
- %% io:fwrite("Root : ~s~n", [Root]),
- NRoot = filename:join([Root, "etc"]),
- file:make_dir(NRoot),
- create_rnd(Root, "etc"), % For all requests
- rootCA(NRoot, OpenSSLCmd, "erlangCA"),
- intermediateCA(NRoot, OpenSSLCmd, "otpCA", "erlangCA"),
- endusers(NRoot, OpenSSLCmd, "otpCA", ["client", "server"]),
- collect_certs(NRoot, ["erlangCA", "otpCA"], ["client", "server"]),
- remove_rnd(Root, "etc").
-
-rootCA(Root, OpenSSLCmd, Name) ->
- create_ca_dir(Root, Name, ca_cnf(Name)),
- DN = #dn{commonName = Name},
- create_self_signed_cert(Root, OpenSSLCmd, Name, req_cnf(DN)),
- ok.
-
-intermediateCA(Root, OpenSSLCmd, CA, ParentCA) ->
- CA = "otpCA",
- create_ca_dir(Root, CA, ca_cnf(CA)),
- CARoot = filename:join([Root, CA]),
- DN = #dn{commonName = CA},
- CnfFile = filename:join([CARoot, "req.cnf"]),
- file:write_file(CnfFile, req_cnf(DN)),
- KeyFile = filename:join([CARoot, "private", "key.pem"]),
- ReqFile = filename:join([CARoot, "req.pem"]),
- create_req(Root, OpenSSLCmd, CnfFile, KeyFile, ReqFile),
- CertFile = filename:join([CARoot, "cert.pem"]),
- sign_req(Root, OpenSSLCmd, ParentCA, "ca_cert", ReqFile, CertFile).
-
-endusers(Root, OpenSSLCmd, CA, Users) ->
- lists:foreach(fun(User) -> enduser(Root, OpenSSLCmd, CA, User) end, Users).
-
-enduser(Root, OpenSSLCmd, CA, User) ->
- UsrRoot = filename:join([Root, User]),
- file:make_dir(UsrRoot),
- CnfFile = filename:join([UsrRoot, "req.cnf"]),
- DN = #dn{commonName = User},
- file:write_file(CnfFile, req_cnf(DN)),
- KeyFile = filename:join([UsrRoot, "key.pem"]),
- ReqFile = filename:join([UsrRoot, "req.pem"]),
- create_req(Root, OpenSSLCmd, CnfFile, KeyFile, ReqFile),
- CertFile = filename:join([UsrRoot, "cert.pem"]),
- sign_req(Root, OpenSSLCmd, CA, "user_cert", ReqFile, CertFile).
-
-collect_certs(Root, CAs, Users) ->
- Bins = lists:foldr(
- fun(CA, Acc) ->
- File = filename:join([Root, CA, "cert.pem"]),
- {ok, Bin} = file:read_file(File),
- [Bin, "\n" | Acc]
- end, [], CAs),
- lists:foreach(
- fun(User) ->
- File = filename:join([Root, User, "cacerts.pem"]),
- file:write_file(File, Bins)
- end, Users).
-
-create_self_signed_cert(Root, OpenSSLCmd, CAName, Cnf) ->
- CARoot = filename:join([Root, CAName]),
- CnfFile = filename:join([CARoot, "req.cnf"]),
- file:write_file(CnfFile, Cnf),
- KeyFile = filename:join([CARoot, "private", "key.pem"]),
- CertFile = filename:join([CARoot, "cert.pem"]),
- Cmd = [OpenSSLCmd, " req"
- " -new"
- " -x509"
- " -config ", CnfFile,
- " -keyout ", KeyFile,
- " -out ", CertFile],
- Env = [{"ROOTDIR", Root}],
- cmd(Cmd, Env).
-
-create_ca_dir(Root, CAName, Cnf) ->
- CARoot = filename:join([Root, CAName]),
- file:make_dir(CARoot),
- create_dirs(CARoot, ["certs", "crl", "newcerts", "private"]),
- create_rnd(Root, filename:join([CAName, "private"])),
- create_files(CARoot, [{"serial", "01\n"},
- {"index.txt", ""},
- {"ca.cnf", Cnf}]).
-
-create_req(Root, OpenSSLCmd, CnfFile, KeyFile, ReqFile) ->
- Cmd = [OpenSSLCmd, " req"
- " -new"
- " -config ", CnfFile,
- " -keyout ", KeyFile,
- " -out ", ReqFile],
- Env = [{"ROOTDIR", Root}],
- cmd(Cmd, Env).
-
-sign_req(Root, OpenSSLCmd, CA, CertType, ReqFile, CertFile) ->
- CACnfFile = filename:join([Root, CA, "ca.cnf"]),
- Cmd = [OpenSSLCmd, " ca"
- " -batch"
- " -notext"
- " -config ", CACnfFile,
- " -extensions ", CertType,
- " -in ", ReqFile,
- " -out ", CertFile],
- Env = [{"ROOTDIR", Root}],
- cmd(Cmd, Env).
+ LongTime = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())+15*365),
+ Validity = {date(), LongTime},
+ Subject = [{email, "[email protected]"},
+ {city, "Stockholm"},
+ {country, "SE"},
+ {org, "erlang"},
+ {org_unit, "testing dep"}],
+
+ RootCa = erl_make_certs:make_cert([{validity, Validity}, {subject, [{name, "erlangCA"}|Subject]}]),
+ ImedCa = erl_make_certs:make_cert([{issuer, RootCa}, {validity, Validity},
+ {subject, [{name, "otpCA"}|Subject]}]),
+ ClientCa = erl_make_certs:make_cert([{issuer, ImedCa}, {validity, Validity},
+ {subject, [{name, "client"}|Subject]}]),
+ ServerCa = erl_make_certs:make_cert([{issuer, ImedCa}, {validity, Validity},
+ {subject, [{name, "server"}|Subject]}]),
+
+ Root0 = filename:dirname(filename:dirname((code:which(?MODULE)))),
+ Root = filename:join([Root0, "etc"]), file:make_dir(Root),
+ CaPath = filename:join([Root, "erlangCA"]), file:make_dir(CaPath),
+ IPath = filename:join([Root, "otpCA"]), file:make_dir(IPath),
+ CPath = filename:join([Root, "client"]), file:make_dir(CPath),
+ SPath = filename:join([Root, "server"]), file:make_dir(SPath),
+
+ erl_make_certs:write_pem(CaPath,"cert", RootCa),
+ erl_make_certs:write_pem(IPath, "cert", ImedCa),
+
+ {ok, CaBin0} = file:read_file(filename:join(CaPath, "cert.pem")),
+ {ok, CaBin1} = file:read_file(filename:join(IPath, "cert.pem")),
+ CaBin = <<CaBin0/binary, CaBin1/binary>>,
+
+ erl_make_certs:write_pem(CPath, "cert", ClientCa),
+ ok = file:write_file(filename:join(CPath, "cacerts.pem"), CaBin),
+ erl_make_certs:write_pem(SPath, "cert", ServerCa),
+ ok = file:write_file(filename:join(SPath, "cacerts.pem"), CaBin),
-%%
-%% Misc
-%%
-
-create_dirs(Root, Dirs) ->
- lists:foreach(fun(Dir) ->
- file:make_dir(filename:join([Root, Dir])) end,
- Dirs).
-
-create_files(Root, NameContents) ->
- lists:foreach(
- fun({Name, Contents}) ->
- file:write_file(filename:join([Root, Name]), Contents) end,
- NameContents).
-
-create_rnd(Root, Dir) ->
- From = filename:join([Root, "rnd", "RAND"]),
- To = filename:join([Root, Dir, "RAND"]),
- file:copy(From, To).
-
-remove_rnd(Root, Dir) ->
- File = filename:join([Root, Dir, "RAND"]),
- file:delete(File).
-
-cmd(Cmd, Env) ->
- FCmd = lists:flatten(Cmd),
- Port = open_port({spawn, FCmd}, [stream, eof, exit_status,
- {env, Env}]),
- eval_cmd(Port).
-
-eval_cmd(Port) ->
- receive
- {Port, {data, _}} ->
- eval_cmd(Port);
- {Port, eof} ->
- ok
- end,
- receive
- {Port, {exit_status, Status}} when Status /= 0 ->
- %% io:fwrite("exit status: ~w~n", [Status]),
- erlang:halt(Status)
- after 0 ->
- ok
- end.
-
-%%
-%% Contents of configuration files
-%%
-
-req_cnf(DN) ->
- ["# Purpose: Configuration for requests (end users and CAs)."
- "\n"
- "ROOTDIR = $ENV::ROOTDIR\n"
- "\n"
-
- "[req]\n"
- "input_password = secret\n"
- "output_password = secret\n"
- "default_bits = 1024\n"
- "RANDFILE = $ROOTDIR/RAND\n"
- "encrypt_key = no\n"
- "default_md = sha1\n"
- "#string_mask = pkix\n"
- "x509_extensions = ca_ext\n"
- "prompt = no\n"
- "distinguished_name= name\n"
- "\n"
-
- "[name]\n"
- "commonName = ", DN#dn.commonName, "\n"
- "organizationalUnitName = ", DN#dn.organizationalUnitName, "\n"
- "organizationName = ", DN#dn.organizationName, "\n"
- "localityName = ", DN#dn.localityName, "\n"
- "countryName = ", DN#dn.countryName, "\n"
- "emailAddress = ", DN#dn.emailAddress, "\n"
- "\n"
-
- "[ca_ext]\n"
- "basicConstraints = critical, CA:true\n"
- "keyUsage = cRLSign, keyCertSign\n"
- "subjectKeyIdentifier = hash\n"
- "subjectAltName = email:copy\n"].
-
-
-ca_cnf(CA) ->
- ["# Purpose: Configuration for CAs.\n"
- "\n"
- "ROOTDIR = $ENV::ROOTDIR\n"
- "default_ca = ca\n"
- "\n"
-
- "[ca]\n"
- "dir = $ROOTDIR/", CA, "\n"
- "certs = $dir/certs\n"
- "crl_dir = $dir/crl\n"
- "database = $dir/index.txt\n"
- "new_certs_dir = $dir/newcerts\n"
- "certificate = $dir/cert.pem\n"
- "serial = $dir/serial\n"
- "crl = $dir/crl.pem\n"
- "private_key = $dir/private/key.pem\n"
- "RANDFILE = $dir/private/RAND\n"
- "\n"
- "x509_extensions = user_cert\n"
- "default_days = 3600\n"
- "default_md = sha1\n"
- "preserve = no\n"
- "policy = policy_match\n"
- "\n"
-
- "[policy_match]\n"
- "commonName = supplied\n"
- "organizationalUnitName = optional\n"
- "organizationName = match\n"
- "countryName = match\n"
- "localityName = match\n"
- "emailAddress = supplied\n"
- "\n"
-
- "[user_cert]\n"
- "basicConstraints = CA:false\n"
- "keyUsage = nonRepudiation, digitalSignature, keyEncipherment\n"
- "subjectKeyIdentifier = hash\n"
- "authorityKeyIdentifier = keyid,issuer:always\n"
- "subjectAltName = email:copy\n"
- "issuerAltName = issuer:copy\n"
- "\n"
-
- "[ca_cert]\n"
- "basicConstraints = critical,CA:true\n"
- "keyUsage = cRLSign, keyCertSign\n"
- "subjectKeyIdentifier = hash\n"
- "authorityKeyIdentifier = keyid:always,issuer:always\n"
- "subjectAltName = email:copy\n"
- "issuerAltName = issuer:copy\n"].
-
+ file:delete(filename:join(CaPath, "cert_key.pem")),
+ file:delete(filename:join(IPath, "cert_key.pem")),
+ file:rename(filename:join(CPath, "cert_key.pem"), filename:join(CPath, "key.pem")),
+ file:rename(filename:join(SPath, "cert_key.pem"), filename:join(SPath, "key.pem")),
+ ok.
diff --git a/lib/ssl/src/ssl.appup.src b/lib/ssl/src/ssl.appup.src
index 65f23e2f74..f4e6b59b6d 100644
--- a/lib/ssl/src/ssl.appup.src
+++ b/lib/ssl/src/ssl.appup.src
@@ -1,30 +1,9 @@
%% -*- erlang -*-
{"%VSN%",
[
- {"3.11.1", [{restart_application, ssl}]},
- {"3.11", [{restart_application, ssl}]},
- {"3.10", [{restart_application, ssl}]},
- {"3.10.1", [{restart_application, ssl}]},
- {"3.10.2", [{restart_application, ssl}]},
- {"3.10.3", [{restart_application, ssl}]},
- {"3.10.4", [{restart_application, ssl}]},
- {"3.10.5", [{restart_application, ssl}]},
- {"3.10.6", [{restart_application, ssl}]},
- {"3.10.7", [{restart_application, ssl}]},
- {"3.10.8", [{restart_application, ssl}]},
- {"3.10.9", [{restart_application, ssl}]}
+ {"4.0.1", [{restart_application, ssl}]}
],
[
- {"3.11.1", [{restart_application, ssl}]},
- {"3.11", [{restart_application, ssl}]},
- {"3.10", [{restart_application, ssl}]},
- {"3.10.1", [{restart_application, ssl}]},
- {"3.10.2", [{restart_application, ssl}]},
- {"3.10.3", [{restart_application, ssl}]},
- {"3.10.4", [{restart_application, ssl}]},
- {"3.10.5", [{restart_application, ssl}]},
- {"3.10.6", [{restart_application, ssl}]},
- {"3.10.8", [{restart_application, ssl}]},
- {"3.10.9", [{restart_application, ssl}]}
+ {"4.0.1", [{restart_application, ssl}]}
]}.
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index df4cd7c84d..7e5929d708 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -77,8 +77,10 @@ stop() ->
application:stop(ssl).
%%--------------------------------------------------------------------
--spec connect(host() | port(), port_num(), list()) -> {ok, #sslsocket{}}.
--spec connect(host() | port(), port_num(), list(), timeout()) -> {ok, #sslsocket{}}.
+-spec connect(host() | port(), list()) -> {ok, #sslsocket{}}.
+-spec connect(host() | port(), list() | port_num(), timeout() | list()) -> {ok, #sslsocket{}}.
+-spec connect(host() | port(), port_num(), list(), timeout()) -> {ok, #sslsocket{}}.
+
%%
%% Description: Connect to a ssl server.
%%--------------------------------------------------------------------
@@ -188,7 +190,8 @@ transport_accept(#sslsocket{} = ListenSocket, Timeout) ->
%%--------------------------------------------------------------------
-spec ssl_accept(#sslsocket{}) -> {ok, #sslsocket{}} | {error, reason()}.
--spec ssl_accept(#sslsocket{}, timeout()) -> {ok, #sslsocket{}} | {error, reason()}.
+-spec ssl_accept(#sslsocket{}, list() | timeout()) -> {ok, #sslsocket{}} | {error, reason()}.
+-spec ssl_accept(port(), list(), timeout()) -> {ok, #sslsocket{}} | {error, reason()}.
%%
%% Description: Performs accept on a ssl listen socket. e.i. performs
%% ssl handshake.
@@ -215,8 +218,8 @@ ssl_accept(Socket, SslOptions, Timeout) when is_port(Socket) ->
{ok, #config{cb=CbInfo,ssl=SslOpts, emulated=EmOpts}} ->
{ok, Port} = inet:port(Socket),
ssl_connection:ssl_accept(Port, Socket,
- {SslOpts, EmOpts},
- self(), CbInfo, Timeout)
+ {SslOpts, EmOpts},
+ self(), CbInfo, Timeout)
catch
Error = {error, _Reason} -> Error
end.
@@ -326,7 +329,7 @@ decode_peercert(BinCert, Opts) ->
{ok, BinCert}
end.
-select_part(otp, {ok, Cert}, Opts) ->
+select_part(otp, Cert, Opts) ->
case lists:member(subject, Opts) of
true ->
TBS = Cert#'OTPCertificate'.tbsCertificate,
@@ -335,7 +338,7 @@ select_part(otp, {ok, Cert}, Opts) ->
{ok, Cert}
end;
-select_part(plain, {ok, Cert}, Opts) ->
+select_part(plain, Cert, Opts) ->
case lists:member(subject, Opts) of
true ->
TBS = Cert#'Certificate'.tbsCertificate,
@@ -374,7 +377,7 @@ cipher_suites(openssl) ->
[ssl_cipher:openssl_suite_name(S) || S <- ssl_cipher:suites(Version)].
%%--------------------------------------------------------------------
--spec getopts(#sslsocket{}, [atom()]) -> {ok, [{atom(), term()}]}| {error, reason()}.
+-spec getopts(#sslsocket{}, [atom()]) -> {ok, [{atom(), term()}]}| {error, reason()}.
%%
%% Description:
%%--------------------------------------------------------------------
@@ -446,8 +449,8 @@ session_info(#sslsocket{pid = Pid, fd = new_ssl}) ->
ssl_connection:session_info(Pid).
%%---------------------------------------------------------------
--spec versions() -> [{{ssl_app, string()}, {supported, [tls_version()]},
- {available, [tls_version()]}}].
+-spec versions() -> [{ssl_app, string()} | {supported, [tls_atom_version()]} |
+ {available, [tls_atom_version()]}].
%%
%% Description: Returns a list of relevant versions.
%%--------------------------------------------------------------------
@@ -457,14 +460,106 @@ versions() ->
AvailableVsns = ?DEFAULT_SUPPORTED_VERSIONS,
[{ssl_app, ?VSN}, {supported, SupportedVsns}, {available, AvailableVsns}].
+
%%---------------------------------------------------------------
-spec renegotiate(#sslsocket{}) -> ok | {error, reason()}.
%%
-%% Description:
+%% Description: Initiates a renegotiation.
%%--------------------------------------------------------------------
renegotiate(#sslsocket{pid = Pid, fd = new_ssl}) ->
ssl_connection:renegotiation(Pid).
+%%---------------------------------------------------------------
+-spec format_error({error, term()}) -> list().
+%%
+%% Description: Creates error string.
+%%--------------------------------------------------------------------
+format_error({error, Reason}) ->
+ format_error(Reason);
+format_error(Reason) when is_list(Reason) ->
+ Reason;
+format_error(closed) ->
+ "The connection is closed";
+format_error(ecacertfile) ->
+ "Own CA certificate file is invalid.";
+format_error(ecertfile) ->
+ "Own certificate file is invalid.";
+format_error(ekeyfile) ->
+ "Own private key file is invalid.";
+format_error(esslaccept) ->
+ "Server SSL handshake procedure between client and server failed.";
+format_error(esslconnect) ->
+ "Client SSL handshake procedure between client and server failed.";
+format_error({eoptions, Options}) ->
+ lists:flatten(io_lib:format("Error in options list: ~p~n", [Options]));
+
+%%%%%%%%%%%% START OLD SSL format_error %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+format_error(ebadsocket) ->
+ "Connection not found (internal error).";
+format_error(ebadstate) ->
+ "Connection not in connect state (internal error).";
+format_error(ebrokertype) ->
+ "Wrong broker type (internal error).";
+format_error(echaintoolong) ->
+ "The chain of certificates provided by peer is too long.";
+format_error(ecipher) ->
+ "Own list of specified ciphers is invalid.";
+format_error(ekeymismatch) ->
+ "Own private key does not match own certificate.";
+format_error(enoissuercert) ->
+ "Cannot find certificate of issuer of certificate provided by peer.";
+format_error(enoservercert) ->
+ "Attempt to do accept without having set own certificate.";
+format_error(enotlistener) ->
+ "Attempt to accept on a non-listening socket.";
+format_error(enoproxysocket) ->
+ "No proxy socket found (internal error or max number of file "
+ "descriptors exceeded).";
+format_error(enooptions) ->
+ "List of options is empty.";
+format_error(enotstarted) ->
+ "The SSL application has not been started.";
+format_error(eoptions) ->
+ "Invalid list of options.";
+format_error(epeercert) ->
+ "Certificate provided by peer is in error.";
+format_error(epeercertexpired) ->
+ "Certificate provided by peer has expired.";
+format_error(epeercertinvalid) ->
+ "Certificate provided by peer is invalid.";
+format_error(eselfsignedcert) ->
+ "Certificate provided by peer is self signed.";
+format_error(esslerrssl) ->
+ "SSL protocol failure. Typically because of a fatal alert from peer.";
+format_error(ewantconnect) ->
+ "Protocol wants to connect, which is not supported in this "
+ "version of the SSL application.";
+format_error(ex509lookup) ->
+ "Protocol wants X.509 lookup, which is not supported in this "
+ "version of the SSL application.";
+format_error({badcall, _Call}) ->
+ "Call not recognized for current mode (active or passive) and state "
+ "of socket.";
+format_error({badcast, _Cast}) ->
+ "Call not recognized for current mode (active or passive) and state "
+ "of socket.";
+
+format_error({badinfo, _Info}) ->
+ "Call not recognized for current mode (active or passive) and state "
+ "of socket.";
+
+%%%%%%%%%%%%%%%%%% END OLD SSL format_error %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+format_error(Error) ->
+ case (catch inet:format_error(Error)) of
+ "unkknown POSIX" ++ _ ->
+ no_format(Error);
+ {'EXIT', _} ->
+ no_format(Error);
+ Other ->
+ Other
+ end.
+
%%%--------------------------------------------------------------
%%% Internal functions
%%%--------------------------------------------------------------------
@@ -520,59 +615,68 @@ old_listen(Port, Options) ->
{ok, Pid} = ssl_broker:start_broker(listener),
ssl_broker:listen(Pid, Port, Options).
-handle_options(Opts0, Role) ->
+handle_options(Opts0, _Role) ->
Opts = proplists:expand([{binary, [{mode, binary}]},
{list, [{mode, list}]}], Opts0),
ReuseSessionFun = fun(_, _, _, _) -> true end,
- AcceptBadCa = fun({bad_cert,unknown_ca}, Acc) -> Acc;
- (Other, Acc) -> [Other | Acc]
- end,
-
- VerifyFun =
- fun(ErrorList) ->
- case lists:foldl(AcceptBadCa, [], ErrorList) of
- [] -> true;
- [_|_] -> false
- end
- end,
+ DefaultVerifyNoneFun =
+ {fun(_,{bad_cert, _}, UserState) ->
+ {valid, UserState};
+ (_,{extension, _}, UserState) ->
+ {unknown, UserState};
+ (_, valid, UserState) ->
+ {valid, UserState};
+ (_, valid_peer, UserState) ->
+ {valid, UserState}
+ end, []},
- UserFailIfNoPeerCert = validate_option(fail_if_no_peer_cert,
- proplists:get_value(fail_if_no_peer_cert, Opts, false)),
+ VerifyNoneFun = handle_option(verify_fun, Opts, DefaultVerifyNoneFun),
- {Verify, FailIfNoPeerCert, CaCertDefault} =
+ UserFailIfNoPeerCert = handle_option(fail_if_no_peer_cert, Opts, false),
+ UserVerifyFun = handle_option(verify_fun, Opts, undefined),
+ CaCerts = handle_option(cacerts, Opts, undefined),
+
+ {Verify, FailIfNoPeerCert, CaCertDefault, VerifyFun} =
%% Handle 0, 1, 2 for backwards compatibility
case proplists:get_value(verify, Opts, verify_none) of
0 ->
- {verify_none, false, ca_cert_default(verify_none, Role)};
+ {verify_none, false,
+ ca_cert_default(verify_none, VerifyNoneFun, CaCerts), VerifyNoneFun};
1 ->
- {verify_peer, false, ca_cert_default(verify_peer, Role)};
+ {verify_peer, false,
+ ca_cert_default(verify_peer, UserVerifyFun, CaCerts), UserVerifyFun};
2 ->
- {verify_peer, true, ca_cert_default(verify_peer, Role)};
+ {verify_peer, true,
+ ca_cert_default(verify_peer, UserVerifyFun, CaCerts), UserVerifyFun};
verify_none ->
- {verify_none, false, ca_cert_default(verify_none, Role)};
+ {verify_none, false,
+ ca_cert_default(verify_none, VerifyNoneFun, CaCerts), VerifyNoneFun};
verify_peer ->
- {verify_peer, UserFailIfNoPeerCert, ca_cert_default(verify_peer, Role)};
+ {verify_peer, UserFailIfNoPeerCert,
+ ca_cert_default(verify_peer, UserVerifyFun, CaCerts), UserVerifyFun};
Value ->
throw({error, {eoptions, {verify, Value}}})
- end,
+ end,
CertFile = handle_option(certfile, Opts, ""),
SSLOptions = #ssl_options{
versions = handle_option(versions, Opts, []),
verify = validate_option(verify, Verify),
- verify_fun = handle_option(verify_fun, Opts, VerifyFun),
+ verify_fun = VerifyFun,
fail_if_no_peer_cert = FailIfNoPeerCert,
verify_client_once = handle_option(verify_client_once, Opts, false),
- validate_extensions_fun = handle_option(validate_extensions_fun, Opts, undefined),
depth = handle_option(depth, Opts, 1),
+ cert = handle_option(cert, Opts, undefined),
certfile = CertFile,
- keyfile = handle_option(keyfile, Opts, CertFile),
key = handle_option(key, Opts, undefined),
+ keyfile = handle_option(keyfile, Opts, CertFile),
password = handle_option(password, Opts, ""),
+ cacerts = CaCerts,
cacertfile = handle_option(cacertfile, Opts, CaCertDefault),
+ dh = handle_option(dh, Opts, undefined),
dhfile = handle_option(dhfile, Opts, undefined),
ciphers = handle_option(ciphers, Opts, []),
%% Server side option
@@ -584,10 +688,10 @@ handle_options(Opts0, Role) ->
},
CbInfo = proplists:get_value(cb_info, Opts, {gen_tcp, tcp, tcp_closed, tcp_error}),
- SslOptions = [versions, verify, verify_fun, validate_extensions_fun,
+ SslOptions = [versions, verify, verify_fun,
fail_if_no_peer_cert, verify_client_once,
- depth, certfile, keyfile,
- key, password, cacertfile, dhfile, ciphers,
+ depth, cert, certfile, key, keyfile,
+ password, cacerts, cacertfile, dh, dhfile, ciphers,
debug, reuse_session, reuse_sessions, ssl_imp,
cb_info, renegotiate_at, secure_renegotiate],
@@ -611,7 +715,25 @@ validate_option(ssl_imp, Value) when Value == new; Value == old ->
validate_option(verify, Value)
when Value == verify_none; Value == verify_peer ->
Value;
-validate_option(verify_fun, Value) when is_function(Value) ->
+validate_option(verify_fun, undefined) ->
+ undefined;
+%% Backwards compatibility
+validate_option(verify_fun, Fun) when is_function(Fun) ->
+ {fun(_,{bad_cert, _} = Reason, OldFun) ->
+ case OldFun([Reason]) of
+ true ->
+ {valid, OldFun};
+ false ->
+ {fail, Reason}
+ end;
+ (_,{extension, _}, UserState) ->
+ {unknown, UserState};
+ (_, valid, UserState) ->
+ {valid, UserState};
+ (_, valid_peer, UserState) ->
+ {valid, UserState}
+ end, Fun};
+validate_option(verify_fun, {Fun, _} = Value) when is_function(Fun) ->
Value;
validate_option(fail_if_no_peer_cert, Value)
when Value == true; Value == false ->
@@ -619,29 +741,38 @@ validate_option(fail_if_no_peer_cert, Value)
validate_option(verify_client_once, Value)
when Value == true; Value == false ->
Value;
-
-validate_option(validate_extensions_fun, Value) when Value == undefined; is_function(Value) ->
- Value;
validate_option(depth, Value) when is_integer(Value),
Value >= 0, Value =< 255->
Value;
-validate_option(certfile, Value) when is_list(Value) ->
+validate_option(cert, Value) when Value == undefined;
+ is_binary(Value) ->
Value;
-validate_option(keyfile, Value) when is_list(Value) ->
+validate_option(certfile, Value) when Value == undefined; is_list(Value) ->
Value;
-validate_option(key, Value) when Value == undefined;
- is_tuple(Value) ->
- %% element(1, Value)=='RSAPrivateKey' ->
+
+validate_option(key, undefined) ->
+ undefined;
+validate_option(key, {KeyType, Value}) when is_binary(Value),
+ KeyType == rsa;
+ KeyType == dsa ->
+ {KeyType, Value};
+validate_option(keyfile, Value) when is_list(Value) ->
Value;
validate_option(password, Value) when is_list(Value) ->
Value;
+validate_option(cacerts, Value) when Value == undefined;
+ is_list(Value) ->
+ Value;
%% certfile must be present in some cases otherwhise it can be set
%% to the empty string.
validate_option(cacertfile, undefined) ->
"";
validate_option(cacertfile, Value) when is_list(Value), Value =/= "" ->
Value;
+validate_option(dh, Value) when Value == undefined;
+ is_binary(Value) ->
+ Value;
validate_option(dhfile, undefined = Value) ->
Value;
validate_option(dhfile, Value) when is_list(Value), Value =/= "" ->
@@ -699,14 +830,16 @@ validate_inet_option(active, Value)
validate_inet_option(_, _) ->
ok.
-ca_cert_default(verify_none, _) ->
+%% The option cacerts overrides cacertsfile
+ca_cert_default(_,_, [_|_]) ->
+ undefined;
+ca_cert_default(verify_none, _, _) ->
undefined;
-%% Client may leave verification up to the user
-ca_cert_default(verify_peer, client) ->
+ca_cert_default(verify_peer, {Fun,_}, _) when is_function(Fun) ->
undefined;
-%% Server that wants to verify_peer must have
+%% Server that wants to verify_peer and has no verify_fun must have
%% some trusted certs.
-ca_cert_default(verify_peer, server) ->
+ca_cert_default(verify_peer, undefined, _) ->
"".
emulated_options() ->
@@ -757,7 +890,7 @@ cipher_suites(Version, [{_,_,_}| _] = Ciphers0) ->
Ciphers = [ssl_cipher:suite(C) || C <- Ciphers0],
cipher_suites(Version, Ciphers);
cipher_suites(Version, [Cipher0 | _] = Ciphers0) when is_binary(Cipher0) ->
- Supported = ssl_cipher:suites(Version),
+ Supported = ssl_cipher:suites(Version) ++ ssl_cipher:anonymous_suites(),
case [Cipher || Cipher <- Ciphers0, lists:member(Cipher, Supported)] of
[] ->
Supported;
@@ -773,92 +906,6 @@ cipher_suites(Version, Ciphers0) ->
Ciphers = [ssl_cipher:openssl_suite(C) || C <- string:tokens(Ciphers0, ":")],
cipher_suites(Version, Ciphers).
-format_error({error, Reason}) ->
- format_error(Reason);
-format_error(Reason) when is_list(Reason) ->
- Reason;
-format_error(closed) ->
- "The connection is closed";
-format_error(ecacertfile) ->
- "Own CA certificate file is invalid.";
-format_error(ecertfile) ->
- "Own certificate file is invalid.";
-format_error(ekeyfile) ->
- "Own private key file is invalid.";
-format_error(esslaccept) ->
- "Server SSL handshake procedure between client and server failed.";
-format_error(esslconnect) ->
- "Client SSL handshake procedure between client and server failed.";
-format_error({eoptions, Options}) ->
- lists:flatten(io_lib:format("Error in options list: ~p~n", [Options]));
-
-%%%%%%%%%%%% START OLD SSL format_error %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-format_error(ebadsocket) ->
- "Connection not found (internal error).";
-format_error(ebadstate) ->
- "Connection not in connect state (internal error).";
-format_error(ebrokertype) ->
- "Wrong broker type (internal error).";
-format_error(echaintoolong) ->
- "The chain of certificates provided by peer is too long.";
-format_error(ecipher) ->
- "Own list of specified ciphers is invalid.";
-format_error(ekeymismatch) ->
- "Own private key does not match own certificate.";
-format_error(enoissuercert) ->
- "Cannot find certificate of issuer of certificate provided by peer.";
-format_error(enoservercert) ->
- "Attempt to do accept without having set own certificate.";
-format_error(enotlistener) ->
- "Attempt to accept on a non-listening socket.";
-format_error(enoproxysocket) ->
- "No proxy socket found (internal error or max number of file "
- "descriptors exceeded).";
-format_error(enooptions) ->
- "List of options is empty.";
-format_error(enotstarted) ->
- "The SSL application has not been started.";
-format_error(eoptions) ->
- "Invalid list of options.";
-format_error(epeercert) ->
- "Certificate provided by peer is in error.";
-format_error(epeercertexpired) ->
- "Certificate provided by peer has expired.";
-format_error(epeercertinvalid) ->
- "Certificate provided by peer is invalid.";
-format_error(eselfsignedcert) ->
- "Certificate provided by peer is self signed.";
-format_error(esslerrssl) ->
- "SSL protocol failure. Typically because of a fatal alert from peer.";
-format_error(ewantconnect) ->
- "Protocol wants to connect, which is not supported in this "
- "version of the SSL application.";
-format_error(ex509lookup) ->
- "Protocol wants X.509 lookup, which is not supported in this "
- "version of the SSL application.";
-format_error({badcall, _Call}) ->
- "Call not recognized for current mode (active or passive) and state "
- "of socket.";
-format_error({badcast, _Cast}) ->
- "Call not recognized for current mode (active or passive) and state "
- "of socket.";
-
-format_error({badinfo, _Info}) ->
- "Call not recognized for current mode (active or passive) and state "
- "of socket.";
-
-%%%%%%%%%%%%%%%%%% END OLD SSL format_error %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-format_error(Error) ->
- case (catch inet:format_error(Error)) of
- "unkknown POSIX" ++ _ ->
- no_format(Error);
- {'EXIT', _} ->
- no_format(Error);
- Other ->
- Other
- end.
-
no_format(Error) ->
lists:flatten(io_lib:format("No format string for error: \"~p\" available.", [Error])).
diff --git a/lib/ssl/src/ssl_app.erl b/lib/ssl/src/ssl_app.erl
index d9a354086d..8d50fd7bdb 100644
--- a/lib/ssl/src/ssl_app.erl
+++ b/lib/ssl/src/ssl_app.erl
@@ -29,14 +29,14 @@
%%--------------------------------------------------------------------
-spec start(normal | {takeover, node()} | {failover, node()}, list()) ->
- {ok, pid()} | {ok, pid(), term()} | {error, term()}.
+ ignore | {ok, pid()} | {error, term()}.
%%--------------------------------------------------------------------
start(_Type, _StartArgs) ->
ssl_sup:start_link().
%--------------------------------------------------------------------
-spec stop(term())-> ok.
-%%--------------------------------------------------------------------
+%%--------------------------------------------------------------------
stop(_State) ->
ok.
diff --git a/lib/ssl/src/ssl_certificate.erl b/lib/ssl/src/ssl_certificate.erl
index 8a79f75725..5571fb01f6 100644
--- a/lib/ssl/src/ssl_certificate.erl
+++ b/lib/ssl/src/ssl_certificate.erl
@@ -31,10 +31,10 @@
-include("ssl_debug.hrl").
-include_lib("public_key/include/public_key.hrl").
--export([trusted_cert_and_path/3,
+-export([trusted_cert_and_path/2,
certificate_chain/2,
file_to_certificats/1,
- validate_extensions/6,
+ validate_extension/3,
is_valid_extkey_usage/2,
is_valid_key_usage/2,
select_extension/2,
@@ -47,61 +47,61 @@
%%====================================================================
%%--------------------------------------------------------------------
--spec trusted_cert_and_path([der_cert()], certdb_ref(), boolean()) ->
- {der_cert(), [der_cert()], list()}.
+-spec trusted_cert_and_path([der_cert()], certdb_ref()) ->
+ {der_cert() | unknown_ca, [der_cert()]}.
%%
%% Description: Extracts the root cert (if not presents tries to
%% look it up, if not found {bad_cert, unknown_ca} will be added verification
%% errors. Returns {RootCert, Path, VerifyErrors}
%%--------------------------------------------------------------------
-trusted_cert_and_path(CertChain, CertDbRef, Verify) ->
- [Cert | RestPath] = lists:reverse(CertChain),
- {ok, OtpCert} = public_key:pkix_decode_cert(Cert, otp),
- IssuerAnPath =
+trusted_cert_and_path(CertChain, CertDbRef) ->
+ Path = [Cert | _] = lists:reverse(CertChain),
+ OtpCert = public_key:pkix_decode_cert(Cert, otp),
+ SignedAndIssuerID =
case public_key:pkix_is_self_signed(OtpCert) of
true ->
{ok, IssuerId} = public_key:pkix_issuer_id(OtpCert, self),
- {IssuerId, RestPath};
- false ->
+ {self, IssuerId};
+ false ->
case public_key:pkix_issuer_id(OtpCert, other) of
{ok, IssuerId} ->
- {IssuerId, [Cert | RestPath]};
+ {other, IssuerId};
{error, issuer_not_found} ->
case find_issuer(OtpCert, no_candidate) of
{ok, IssuerId} ->
- {IssuerId, [Cert | RestPath]};
+ {other, IssuerId};
Other ->
- {Other, RestPath}
+ Other
end
end
end,
- case IssuerAnPath of
- {{error, issuer_not_found}, _ } ->
- %% The root CA was not sent and can not be found, we fail if verify = true
- not_valid(?ALERT_REC(?FATAL, ?UNKNOWN_CA), Verify, {Cert, RestPath});
- {{SerialNr, Issuer}, Path} ->
- case ssl_manager:lookup_trusted_cert(CertDbRef,
- SerialNr, Issuer) of
+ case SignedAndIssuerID of
+ {error, issuer_not_found} ->
+ %% The root CA was not sent and can not be found.
+ {unknown_ca, Path};
+ {self, _} when length(Path) == 1 ->
+ {selfsigned_peer, Path};
+ {_ ,{SerialNr, Issuer}} ->
+ case ssl_manager:lookup_trusted_cert(CertDbRef, SerialNr, Issuer) of
{ok, {BinCert,_}} ->
- {BinCert, Path, []};
+ {BinCert, Path};
_ ->
- %% Fail if verify = true
- not_valid(?ALERT_REC(?FATAL, ?UNKNOWN_CA),
- Verify, {Cert, RestPath})
+ %% Root CA could not be verified
+ {unknown_ca, Path}
end
end.
%%--------------------------------------------------------------------
-spec certificate_chain(undefined | binary(), certdb_ref()) ->
- {error, no_cert} | [der_cert()].
+ {error, no_cert} | {ok, [der_cert()]}.
%%
%% Description: Return the certificate chain to send to peer.
%%--------------------------------------------------------------------
certificate_chain(undefined, _CertsDbRef) ->
{error, no_cert};
certificate_chain(OwnCert, CertsDbRef) ->
- {ok, ErlCert} = public_key:pkix_decode_cert(OwnCert, otp),
+ ErlCert = public_key:pkix_decode_cert(OwnCert, otp),
certificate_chain(ErlCert, OwnCert, CertsDbRef, [OwnCert]).
%%--------------------------------------------------------------------
-spec file_to_certificats(string()) -> [der_cert()].
@@ -110,34 +110,31 @@ certificate_chain(OwnCert, CertsDbRef) ->
%%--------------------------------------------------------------------
file_to_certificats(File) ->
{ok, List} = ssl_manager:cache_pem_file(File),
- [Bin || {cert, Bin, not_encrypted} <- List].
+ [Bin || {'Certificate', Bin, not_encrypted} <- List].
%%--------------------------------------------------------------------
--spec validate_extensions([#'Extension'{}], term(), [#'Extension'{}],
- boolean(), list(), client | server) -> {[#'Extension'{}], term(), list()}.
+-spec validate_extension(term(), #'Extension'{} | {bad_cert, atom()} | valid,
+ term()) -> {valid, term()} |
+ {fail, tuple()} |
+ {unknown, term()}.
%%
%% Description: Validates ssl/tls specific extensions
%%--------------------------------------------------------------------
-validate_extensions([], ValidationState, UnknownExtensions, _, AccErr, _) ->
- {UnknownExtensions, ValidationState, AccErr};
-
-validate_extensions([#'Extension'{extnID = ?'id-ce-extKeyUsage',
- extnValue = KeyUse,
- critical = true} | Rest],
- ValidationState, UnknownExtensions, Verify, AccErr0, Role) ->
+validate_extension(_,{extension, #'Extension'{extnID = ?'id-ce-extKeyUsage',
+ extnValue = KeyUse}}, Role) ->
case is_valid_extkey_usage(KeyUse, Role) of
true ->
- validate_extensions(Rest, ValidationState, UnknownExtensions,
- Verify, AccErr0, Role);
+ {valid, Role};
false ->
- AccErr =
- not_valid_extension({bad_cert, invalid_ext_key_usage}, Verify, AccErr0),
- validate_extensions(Rest, ValidationState, UnknownExtensions, Verify, AccErr, Role)
+ {fail, {bad_cert, invalid_ext_key_usage}}
end;
-
-validate_extensions([Extension | Rest], ValidationState, UnknownExtensions,
- Verify, AccErr, Role) ->
- validate_extensions(Rest, ValidationState, [Extension | UnknownExtensions],
- Verify, AccErr, Role).
+validate_extension(_, {bad_cert, _} = Reason, _) ->
+ {fail, Reason};
+validate_extension(_, {extension, _}, Role) ->
+ {unknown, Role};
+validate_extension(_, valid, Role) ->
+ {valid, Role};
+validate_extension(_, valid_peer, Role) ->
+ {valid, Role}.
%%--------------------------------------------------------------------
-spec is_valid_key_usage(list(), term()) -> boolean().
@@ -219,7 +216,7 @@ certificate_chain(CertsDbRef, Chain, SerialNr, Issuer, _SelfSigned) ->
case ssl_manager:lookup_trusted_cert(CertsDbRef,
SerialNr, Issuer) of
{ok, {IssuerCert, ErlCert}} ->
- {ok, ErlCert} = public_key:pkix_decode_cert(IssuerCert, otp),
+ ErlCert = public_key:pkix_decode_cert(IssuerCert, otp),
certificate_chain(ErlCert, IssuerCert,
CertsDbRef, [IssuerCert | Chain]);
_ ->
@@ -244,19 +241,9 @@ find_issuer(OtpCert, PrevCandidateKey) ->
end
end.
-not_valid(Alert, true, _) ->
- throw(Alert);
-not_valid(_, false, {ErlCert, Path}) ->
- {ErlCert, Path, [{bad_cert, unknown_ca}]}.
-
is_valid_extkey_usage(KeyUse, client) ->
%% Client wants to verify server
is_valid_key_usage(KeyUse,?'id-kp-serverAuth');
is_valid_extkey_usage(KeyUse, server) ->
%% Server wants to verify client
is_valid_key_usage(KeyUse, ?'id-kp-clientAuth').
-
-not_valid_extension(Error, true, _) ->
- throw(Error);
-not_valid_extension(Error, false, AccErrors) ->
- [Error | AccErrors].
diff --git a/lib/ssl/src/ssl_certificate_db.erl b/lib/ssl/src/ssl_certificate_db.erl
index e953821057..2a5a7f3394 100644
--- a/lib/ssl/src/ssl_certificate_db.erl
+++ b/lib/ssl/src/ssl_certificate_db.erl
@@ -54,10 +54,9 @@ remove(Dbs) ->
lists:foreach(fun(Db) -> true = ets:delete(Db) end, Dbs).
%%--------------------------------------------------------------------
--spec lookup_trusted_cert(reference(), serialnumber(), issuer()) -> {der_cert(), #'OTPCertificate'{}}.
+-spec lookup_trusted_cert(reference(), serialnumber(), issuer()) ->
+ undefined | {ok, {der_cert(), #'OTPCertificate'{}}}.
-%% SerialNumber = integer()
-%% Issuer = {rdnSequence, IssuerAttrs}
%%
%% Description: Retrives the trusted certificate identified by
%% <SerialNumber, Issuer>. Ref is used as it is specified
@@ -75,12 +74,16 @@ lookup_cached_certs(File) ->
ets:lookup(certificate_db_name(), {file, File}).
%%--------------------------------------------------------------------
--spec add_trusted_certs(pid(), string(), certdb_ref()) -> {ok, certdb_ref()}.
+-spec add_trusted_certs(pid(), string() | {der, list()}, certdb_ref()) -> {ok, certdb_ref()}.
%%
%% Description: Adds the trusted certificates from file <File> to the
%% runtime database. Returns Ref that should be handed to lookup_trusted_cert
%% together with the cert serialnumber and issuer.
%%--------------------------------------------------------------------
+add_trusted_certs(_Pid, {der, DerList}, [CerDb, _,_]) ->
+ NewRef = make_ref(),
+ add_certs_from_der(DerList, NewRef, CerDb),
+ {ok, NewRef};
add_trusted_certs(Pid, File, [CertsDb, FileToRefDb, PidToFileDb]) ->
Ref = case lookup(File, FileToRefDb) of
undefined ->
@@ -94,17 +97,17 @@ add_trusted_certs(Pid, File, [CertsDb, FileToRefDb, PidToFileDb]) ->
end,
insert(Pid, File, PidToFileDb),
{ok, Ref}.
-
%%--------------------------------------------------------------------
-spec cache_pem_file(pid(), string(), certdb_ref()) -> term().
%%
%% Description: Cache file as binary in DB
%%--------------------------------------------------------------------
cache_pem_file(Pid, File, [CertsDb, _FileToRefDb, PidToFileDb]) ->
- Res = {ok, Content} = public_key:pem_to_der(File),
+ {ok, PemBin} = file:read_file(File),
+ Content = public_key:pem_decode(PemBin),
insert({file, File}, Content, CertsDb),
insert(Pid, File, PidToFileDb),
- Res.
+ {ok, Content}.
%%--------------------------------------------------------------------
-spec remove_trusted_certs(pid(), certdb_ref()) -> term().
@@ -138,13 +141,13 @@ remove_trusted_certs(Pid, [CertsDb, FileToRefDb, PidToFileDb]) ->
end.
%%--------------------------------------------------------------------
--spec issuer_candidate(no_candidate | cert_key()) ->
- {cert_key(), der_cert()} | no_more_candidates.
+-spec issuer_candidate(no_candidate | cert_key() | {file, term()}) ->
+ {cert_key(),{der_cert(), #'OTPCertificate'{}}} | no_more_candidates.
%%
%% Description: If a certificat does not define its issuer through
%% the extension 'ce-authorityKeyIdentifier' we can
%% try to find the issuer in the database over known
-%% certificates.
+%% certificates.
%%--------------------------------------------------------------------
issuer_candidate(no_candidate) ->
Db = certificate_db_name(),
@@ -202,15 +205,26 @@ lookup(Key, Db) ->
remove_certs(Ref, CertsDb) ->
ets:match_delete(CertsDb, {{Ref, '_', '_'}, '_'}).
+add_certs_from_der(DerList, Ref, CertsDb) ->
+ Add = fun(Cert) -> add_certs(Cert, Ref, CertsDb) end,
+ [Add(Cert) || Cert <- DerList].
+
add_certs_from_file(File, Ref, CertsDb) ->
- Decode = fun(Cert) ->
- {ok, ErlCert} = public_key:pkix_decode_cert(Cert, otp),
- TBSCertificate = ErlCert#'OTPCertificate'.tbsCertificate,
- SerialNumber = TBSCertificate#'OTPTBSCertificate'.serialNumber,
- Issuer = public_key:pkix_normalize_general_name(
- TBSCertificate#'OTPTBSCertificate'.issuer),
- insert({Ref, SerialNumber, Issuer}, {Cert,ErlCert}, CertsDb)
- end,
- {ok,Der} = public_key:pem_to_der(File),
- [Decode(Cert) || {cert, Cert, not_encrypted} <- Der].
+ Add = fun(Cert) -> add_certs(Cert, Ref, CertsDb) end,
+ {ok, PemBin} = file:read_file(File),
+ PemEntries = public_key:pem_decode(PemBin),
+ [Add(Cert) || {'Certificate', Cert, not_encrypted} <- PemEntries].
+add_certs(Cert, Ref, CertsDb) ->
+ try ErlCert = public_key:pkix_decode_cert(Cert, otp),
+ TBSCertificate = ErlCert#'OTPCertificate'.tbsCertificate,
+ SerialNumber = TBSCertificate#'OTPTBSCertificate'.serialNumber,
+ Issuer = public_key:pkix_normalize_name(
+ TBSCertificate#'OTPTBSCertificate'.issuer),
+ insert({Ref, SerialNumber, Issuer}, {Cert,ErlCert}, CertsDb)
+ catch
+ error:_ ->
+ Report = io_lib:format("SSL WARNING: Ignoring a CA cert as "
+ "it could not be correctly decoded.~n", []),
+ error_logger:info_report(Report)
+ end.
diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl
index a6e80047c2..175d589931 100644
--- a/lib/ssl/src/ssl_cipher.erl
+++ b/lib/ssl/src/ssl_cipher.erl
@@ -34,13 +34,13 @@
-export([security_parameters/2, suite_definition/1,
decipher/5, cipher/4,
- suite/1, suites/1,
+ suite/1, suites/1, anonymous_suites/0,
openssl_suite/1, openssl_suite_name/1, filter/2]).
-compile(inline).
%%--------------------------------------------------------------------
--spec security_parameters(erl_cipher_suite(), #security_parameters{}) ->
+-spec security_parameters(cipher_suite(), #security_parameters{}) ->
#security_parameters{}.
%%
%% Description: Returns a security parameters record where the
@@ -119,7 +119,7 @@ block_cipher(Fun, BlockSz, #cipher_state{key=Key, iv=IV} = CS0,
%%--------------------------------------------------------------------
-spec decipher(cipher_enum(), integer(), #cipher_state{}, binary(), tls_version()) ->
- {binary(), #cipher_state{}}.
+ {binary(), binary(), #cipher_state{}} | #alert{}.
%%
%% Description: Decrypts the data and the MAC using cipher described
%% by cipher_enum() and updating the cipher state.
@@ -164,22 +164,22 @@ decipher(?AES, HashSz, CipherState, Fragment, Version) ->
block_decipher(Fun, #cipher_state{key=Key, iv=IV} = CipherState0,
HashSz, Fragment, Version) ->
- ?DBG_HEX(Key),
- ?DBG_HEX(IV),
- ?DBG_HEX(Fragment),
- T = Fun(Key, IV, Fragment),
- ?DBG_HEX(T),
- GBC = generic_block_cipher_from_bin(T, HashSz),
- case is_correct_padding(GBC, Version) of
- true ->
- Content = GBC#generic_block_cipher.content,
- Mac = GBC#generic_block_cipher.mac,
- CipherState1 = CipherState0#cipher_state{iv=next_iv(Fragment, IV)},
- {Content, Mac, CipherState1};
- false ->
- ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
+ try Fun(Key, IV, Fragment) of
+ Text ->
+ GBC = generic_block_cipher_from_bin(Text, HashSz),
+ case is_correct_padding(GBC, Version) of
+ true ->
+ Content = GBC#generic_block_cipher.content,
+ Mac = GBC#generic_block_cipher.mac,
+ CipherState1 = CipherState0#cipher_state{iv=next_iv(Fragment, IV)},
+ {Content, Mac, CipherState1};
+ false ->
+ ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
+ end
+ catch
+ _:_ ->
+ ?ALERT_REC(?FATAL, ?DECRYPTION_FAILED)
end.
-
%%--------------------------------------------------------------------
-spec suites(tls_version()) -> [cipher_suite()].
%%
@@ -191,6 +191,19 @@ suites({3, N}) when N == 1; N == 2 ->
ssl_tls1:suites().
%%--------------------------------------------------------------------
+-spec anonymous_suites() -> [cipher_suite()].
+%%
+%% Description: Returns a list of the anonymous cipher suites, only supported
+%% if explicitly set by user. Intended only for testing.
+%%--------------------------------------------------------------------
+anonymous_suites() ->
+ [?TLS_DH_anon_WITH_RC4_128_MD5,
+ ?TLS_DH_anon_WITH_DES_CBC_SHA,
+ ?TLS_DH_anon_WITH_3DES_EDE_CBC_SHA,
+ ?TLS_DH_anon_WITH_AES_128_CBC_SHA,
+ ?TLS_DH_anon_WITH_AES_256_CBC_SHA].
+
+%%--------------------------------------------------------------------
-spec suite_definition(cipher_suite()) -> erl_cipher_suite().
%%
%% Description: Return erlang cipher suite definition.
@@ -235,7 +248,20 @@ suite_definition(?TLS_RSA_WITH_AES_256_CBC_SHA) ->
suite_definition(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA) ->
{dhe_dss, aes_256_cbc, sha};
suite_definition(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA) ->
- {dhe_rsa, aes_256_cbc, sha}.
+ {dhe_rsa, aes_256_cbc, sha};
+
+%%% DH-ANON deprecated by TLS spec and not available
+%%% by default, but good for testing purposes.
+suite_definition(?TLS_DH_anon_WITH_RC4_128_MD5) ->
+ {dh_anon, rc4_128, md5};
+suite_definition(?TLS_DH_anon_WITH_DES_CBC_SHA) ->
+ {dh_anon, des_cbc, sha};
+suite_definition(?TLS_DH_anon_WITH_3DES_EDE_CBC_SHA) ->
+ {dh_anon, '3des_ede_cbc', sha};
+suite_definition(?TLS_DH_anon_WITH_AES_128_CBC_SHA) ->
+ {dh_anon, aes_128_cbc, sha};
+suite_definition(?TLS_DH_anon_WITH_AES_256_CBC_SHA) ->
+ {dh_anon, aes_256_cbc, sha}.
%%--------------------------------------------------------------------
-spec suite(erl_cipher_suite()) -> cipher_suite().
@@ -266,12 +292,12 @@ suite({dhe_rsa, des_cbc, sha}) ->
?TLS_DHE_RSA_WITH_DES_CBC_SHA;
suite({dhe_rsa, '3des_ede_cbc', sha}) ->
?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
-%% suite({dh_anon, rc4_128, md5}) ->
-%% ?TLS_DH_anon_WITH_RC4_128_MD5;
-%% suite({dh_anon, des40_cbc, sha}) ->
-%% ?TLS_DH_anon_WITH_DES_CBC_SHA;
-%% suite({dh_anon, '3des_ede_cbc', sha}) ->
-%% ?TLS_DH_anon_WITH_3DES_EDE_CBC_SHA;
+suite({dh_anon, rc4_128, md5}) ->
+ ?TLS_DH_anon_WITH_RC4_128_MD5;
+suite({dh_anon, des_cbc, sha}) ->
+ ?TLS_DH_anon_WITH_DES_CBC_SHA;
+suite({dh_anon, '3des_ede_cbc', sha}) ->
+ ?TLS_DH_anon_WITH_3DES_EDE_CBC_SHA;
%%% TSL V1.1 AES suites
suite({rsa, aes_128_cbc, sha}) ->
@@ -280,16 +306,16 @@ suite({dhe_dss, aes_128_cbc, sha}) ->
?TLS_DHE_DSS_WITH_AES_128_CBC_SHA;
suite({dhe_rsa, aes_128_cbc, sha}) ->
?TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
-%% suite({dh_anon, aes_128_cbc, sha}) ->
-%% ?TLS_DH_anon_WITH_AES_128_CBC_SHA;
+suite({dh_anon, aes_128_cbc, sha}) ->
+ ?TLS_DH_anon_WITH_AES_128_CBC_SHA;
suite({rsa, aes_256_cbc, sha}) ->
?TLS_RSA_WITH_AES_256_CBC_SHA;
suite({dhe_dss, aes_256_cbc, sha}) ->
?TLS_DHE_DSS_WITH_AES_256_CBC_SHA;
suite({dhe_rsa, aes_256_cbc, sha}) ->
- ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA.
-%% suite({dh_anon, aes_256_cbc, sha}) ->
-%% ?TLS_DH_anon_WITH_AES_256_CBC_SHA.
+ ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
+suite({dh_anon, aes_256_cbc, sha}) ->
+ ?TLS_DH_anon_WITH_AES_256_CBC_SHA.
%%--------------------------------------------------------------------
-spec openssl_suite(openssl_cipher_suite()) -> cipher_suite().
@@ -370,7 +396,7 @@ openssl_suite_name(Cipher) ->
filter(undefined, Ciphers) ->
Ciphers;
filter(DerCert, Ciphers) ->
- {ok, OtpCert} = public_key:pkix_decode_cert(DerCert, otp),
+ OtpCert = public_key:pkix_decode_cert(DerCert, otp),
SigAlg = OtpCert#'OTPCertificate'.signatureAlgorithm,
case ssl_certificate:signature_type(SigAlg#'SignatureAlgorithm'.algorithm) of
rsa ->
@@ -506,6 +532,12 @@ generic_stream_cipher_from_bin(T, HashSz) ->
is_correct_padding(_, {3, 0}) ->
true;
+%% For interoperability reasons we do not check the padding in TLS 1.0 as it
+%% is not strictly required and breaks interopability with for instance
+%% Google.
+is_correct_padding(_, {3, 1}) ->
+ true;
+%% Padding must be check in TLS 1.1 and after
is_correct_padding(#generic_block_cipher{padding_length = Len, padding = Padding}, _) ->
list_to_binary(lists:duplicate(Len, Len)) == Padding.
@@ -574,5 +606,3 @@ filter_rsa_suites(Use, KeyUse, CipherSuits, RsaSuites) ->
false ->
CipherSuits -- RsaSuites
end.
-
-
diff --git a/lib/ssl/src/ssl_cipher.hrl b/lib/ssl/src/ssl_cipher.hrl
index 19de709d9c..8bd68cc190 100644
--- a/lib/ssl/src/ssl_cipher.hrl
+++ b/lib/ssl/src/ssl_cipher.hrl
@@ -28,7 +28,7 @@
-type cipher() :: null |rc4_128 | idea_cbc | des40_cbc | des_cbc | '3des_ede_cbc'
| aes_128_cbc | aes_256_cbc.
--type hash() :: sha | md5.
+-type hash() :: null | sha | md5.
-type erl_cipher_suite() :: {key_algo(), cipher(), hash()}.
-type cipher_suite() :: binary().
-type cipher_enum() :: integer().
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl
index 5b4b129e30..3a9cada81e 100644
--- a/lib/ssl/src/ssl_connection.erl
+++ b/lib/ssl/src/ssl_connection.erl
@@ -75,7 +75,7 @@
session, % #session{} from ssl_handshake.hrl
session_cache, %
session_cache_cb, %
- negotiated_version, % #protocol_version{}
+ negotiated_version, % tls_version()
supported_protocol_versions, % [atom()]
client_certificate_requested = false,
key_algorithm, % atom as defined by cipher_suite
@@ -125,8 +125,9 @@ send(Pid, Data) ->
recv(Pid, Length, Timeout) ->
sync_send_all_state_event(Pid, {recv, Length}, Timeout).
%%--------------------------------------------------------------------
--spec connect(host(), port_num(), port(), list(), pid(), tuple(), timeout()) ->
- {ok, #sslsocket{}} | {error, reason()}.
+-spec connect(host(), port_num(), port(), {#ssl_options{}, #socket_options{}},
+ pid(), tuple(), timeout()) ->
+ {ok, #sslsocket{}} | {error, reason()}.
%%
%% Description: Connect to a ssl server.
%%--------------------------------------------------------------------
@@ -138,7 +139,8 @@ connect(Host, Port, Socket, Options, User, CbInfo, Timeout) ->
{error, ssl_not_started}
end.
%%--------------------------------------------------------------------
--spec ssl_accept(port_num(), port(), list(), pid(), tuple(), timeout()) ->
+-spec ssl_accept(port_num(), port(), {#ssl_options{}, #socket_options{}},
+ pid(), tuple(), timeout()) ->
{ok, #sslsocket{}} | {error, reason()}.
%%
%% Description: Performs accept on a ssl listen socket. e.i. performs
@@ -253,7 +255,7 @@ session_info(ConnectionPid) ->
sync_send_all_state_event(ConnectionPid, session_info).
%%--------------------------------------------------------------------
--spec peer_certificate(pid()) -> {ok, binary()} | {error, reason()}.
+-spec peer_certificate(pid()) -> {ok, binary()| undefined} | {error, reason()}.
%%
%% Description: Returns the peer cert
%%--------------------------------------------------------------------
@@ -288,9 +290,10 @@ start_link(Role, Host, Port, Socket, Options, User, CbInfo) ->
%% gen_fsm callbacks
%%====================================================================
%%--------------------------------------------------------------------
--spec init(list()) -> {ok, state_name(), #state{}}
- | {ok, state_name(), #state{}, timeout()} |
- ignore | {stop, term()}.
+-spec init(list()) -> {ok, state_name(), #state{}} | {stop, term()}.
+%% Possible return values not used now.
+%% | {ok, state_name(), #state{}, timeout()} |
+%% ignore
%% Description:Whenever a gen_fsm is started using gen_fsm:start/[3,4] or
%% gen_fsm:start_link/3,4, this function is called by the new process to
%% initialize.
@@ -331,14 +334,12 @@ hello(start, #state{host = Host, port = Port, role = client,
ssl_options = SslOpts,
transport_cb = Transport, socket = Socket,
connection_states = ConnectionStates,
- own_cert = Cert,
renegotiation = {Renegotiation, _}}
= State0) ->
Hello = ssl_handshake:client_hello(Host, Port,
ConnectionStates,
- SslOpts, Cert,
- Renegotiation),
+ SslOpts, Renegotiation),
Version = Hello#client_hello.client_version,
Hashes0 = ssl_handshake:init_hashes(),
@@ -350,7 +351,7 @@ hello(start, #state{host = Host, port = Port, role = client,
session =
#session{session_id = Hello#client_hello.session_id,
is_resumable = false},
- tls_handshake_hashes = Hashes1},
+ tls_handshake_hashes = Hashes1},
{Record, State} = next_record(State1),
next_state(hello, Record, State);
@@ -373,7 +374,7 @@ hello(#server_hello{cipher_suite = CipherSuite,
case ssl_handshake:hello(Hello, SslOptions, ConnectionStates0, Renegotiation) of
{Version, NewId, ConnectionStates} ->
- {KeyAlgorithm, _, _} =
+ {KeyAlgorithm, _, _} =
ssl_cipher:suite_definition(CipherSuite),
PremasterSecret = make_premaster_secret(ReqVersion, KeyAlgorithm),
@@ -499,8 +500,7 @@ certify(#certificate{} = Cert,
ssl_options = Opts} = State) ->
case ssl_handshake:certify(Cert, CertDbRef, Opts#ssl_options.depth,
Opts#ssl_options.verify,
- Opts#ssl_options.verify_fun,
- Opts#ssl_options.validate_extensions_fun, Role) of
+ Opts#ssl_options.verify_fun, Role) of
{PeerCert, PublicKeyInfo} ->
handle_peer_cert(PeerCert, PublicKeyInfo,
State#state{client_certificate_requested = false});
@@ -512,7 +512,7 @@ certify(#certificate{} = Cert,
certify(#server_key_exchange{} = KeyExchangeMsg,
#state{role = client, negotiated_version = Version,
key_algorithm = Alg} = State0)
- when Alg == dhe_dss; Alg == dhe_rsa ->
+ when Alg == dhe_dss; Alg == dhe_rsa; Alg == dh_anon ->
case handle_server_key(KeyExchangeMsg, State0) of
#state{} = State1 ->
{Record, State} = next_record(State1),
@@ -576,69 +576,54 @@ certify(#client_key_exchange{} = Msg,
%% We expect a certificate here
handle_unexpected_message(Msg, certify_client_key_exchange, State);
-certify(#client_key_exchange{exchange_keys
- = #encrypted_premaster_secret{premaster_secret
- = EncPMS}},
- #state{negotiated_version = Version,
- connection_states = ConnectionStates0,
- session = Session0,
- private_key = Key} = State0) ->
- try ssl_handshake:decrypt_premaster_secret(EncPMS, Key) of
- PremasterSecret ->
- case ssl_handshake:master_secret(Version, PremasterSecret,
- ConnectionStates0, server) of
- {MasterSecret, ConnectionStates} ->
- Session = Session0#session{master_secret = MasterSecret},
- State1 = State0#state{connection_states = ConnectionStates,
- session = Session},
- {Record, State} = next_record(State1),
- next_state(cipher, Record, State);
- #alert{} = Alert ->
- handle_own_alert(Alert, Version,
- certify_client_key_exchange, State0),
- {stop, normal, State0}
- end
+certify(#client_key_exchange{exchange_keys = Keys},
+ State = #state{key_algorithm = KeyAlg, negotiated_version = Version}) ->
+ try
+ certify_client_key_exchange(ssl_handshake:decode_client_key(Keys, KeyAlg, Version), State)
catch
#alert{} = Alert ->
- handle_own_alert(Alert, Version, certify_client_key_exchange,
- State0),
- {stop, normal, State0}
+ handle_own_alert(Alert, Version, certify_client_key_exchange, State),
+ {stop, normal, State}
end;
-certify(#client_key_exchange{exchange_keys = #client_diffie_hellman_public{
- dh_public = ClientPublicDhKey}},
- #state{negotiated_version = Version,
- diffie_hellman_params = #'DHParameter'{prime = P,
- base = G},
- diffie_hellman_keys = {_, ServerDhPrivateKey},
- role = Role,
- session = Session,
- connection_states = ConnectionStates0} = State0) ->
-
- PMpint = crypto:mpint(P),
- GMpint = crypto:mpint(G),
- PremasterSecret = crypto:dh_compute_key(mpint_binary(ClientPublicDhKey),
- ServerDhPrivateKey,
- [PMpint, GMpint]),
-
+certify(Msg, State) ->
+ handle_unexpected_message(Msg, certify, State).
+
+certify_client_key_exchange(#encrypted_premaster_secret{premaster_secret= EncPMS},
+ #state{negotiated_version = Version,
+ connection_states = ConnectionStates0,
+ session = Session0,
+ private_key = Key} = State0) ->
+ PremasterSecret = ssl_handshake:decrypt_premaster_secret(EncPMS, Key),
case ssl_handshake:master_secret(Version, PremasterSecret,
- ConnectionStates0, Role) of
+ ConnectionStates0, server) of
{MasterSecret, ConnectionStates} ->
- State1 = State0#state{session =
- Session#session{master_secret
- = MasterSecret},
- connection_states = ConnectionStates},
-
+ Session = Session0#session{master_secret = MasterSecret},
+ State1 = State0#state{connection_states = ConnectionStates,
+ session = Session},
{Record, State} = next_record(State1),
next_state(cipher, Record, State);
#alert{} = Alert ->
- handle_own_alert(Alert, Version,
+ handle_own_alert(Alert, Version,
certify_client_key_exchange, State0),
{stop, normal, State0}
end;
-certify(Msg, State) ->
- handle_unexpected_message(Msg, certify, State).
+certify_client_key_exchange(#client_diffie_hellman_public{dh_public = ClientPublicDhKey},
+ #state{negotiated_version = Version,
+ diffie_hellman_params = #'DHParameter'{prime = P,
+ base = G},
+ diffie_hellman_keys = {_, ServerDhPrivateKey}} = State0) ->
+
+ case dh_master_secret(crypto:mpint(P), crypto:mpint(G), ClientPublicDhKey, ServerDhPrivateKey, State0) of
+ #state{} = State1 ->
+ {Record, State} = next_record(State1),
+ next_state(cipher, Record, State);
+ #alert{} = Alert ->
+ handle_own_alert(Alert, Version,
+ certify_client_key_exchange, State0),
+ {stop, normal, State0}
+ end.
%%--------------------------------------------------------------------
-spec cipher(#hello_request{} | #certificate_verify{} | #finished{} | term(),
@@ -653,12 +638,10 @@ cipher(#certificate_verify{signature = Signature},
public_key_info = PublicKeyInfo,
negotiated_version = Version,
session = #session{master_secret = MasterSecret},
- key_algorithm = Algorithm,
tls_handshake_hashes = Hashes
} = State0) ->
case ssl_handshake:certificate_verify(Signature, PublicKeyInfo,
- Version, MasterSecret,
- Algorithm, Hashes) of
+ Version, MasterSecret, Hashes) of
valid ->
{Record, State} = next_record(State0),
next_state(cipher, Record, State);
@@ -698,14 +681,13 @@ connection(#hello_request{}, #state{host = Host, port = Port,
socket = Socket,
ssl_options = SslOpts,
negotiated_version = Version,
- own_cert = Cert,
transport_cb = Transport,
connection_states = ConnectionStates0,
renegotiation = {Renegotiation, _},
tls_handshake_hashes = Hashes0} = State0) ->
- Hello = ssl_handshake:client_hello(Host, Port,
- ConnectionStates0, SslOpts, Cert, Renegotiation),
+ Hello = ssl_handshake:client_hello(Host, Port, ConnectionStates0,
+ SslOpts, Renegotiation),
{BinMsg, ConnectionStates1, Hashes1} =
encode_handshake(Hello, Version, ConnectionStates0, Hashes0),
@@ -720,7 +702,9 @@ connection(#client_hello{} = Hello, #state{role = server} = State) ->
connection(Msg, State) ->
handle_unexpected_message(Msg, connection, State).
%%--------------------------------------------------------------------
--spec handle_event(term(), state_name(), #state{}) -> gen_fsm_state_return().
+-spec handle_event(term(), state_name(), #state{}) -> term().
+%% As it is not currently used gen_fsm_state_return() makes
+%% dialyzer unhappy!
%%
%% Description: Whenever a gen_fsm receives an event sent using
%% gen_fsm:send_all_state_event/2, this function is called to handle
@@ -1033,83 +1017,104 @@ ssl_init(SslOpts, Role) ->
PrivateKey =
init_private_key(SslOpts#ssl_options.key, SslOpts#ssl_options.keyfile,
SslOpts#ssl_options.password, Role),
- DHParams = init_diffie_hellman(SslOpts#ssl_options.dhfile, Role),
+ DHParams = init_diffie_hellman(SslOpts#ssl_options.dh, SslOpts#ssl_options.dhfile, Role),
{ok, CertDbRef, CacheRef, OwnCert, PrivateKey, DHParams}.
-init_certificates(#ssl_options{cacertfile = CACertFile,
- certfile = CertFile}, Role) ->
-
- case ssl_manager:connection_init(CACertFile, Role) of
- {ok, CertDbRef, CacheRef} ->
- init_certificates(CertDbRef, CacheRef, CertFile, Role);
- {error, Reason} ->
- handle_file_error(?LINE, error, Reason, CACertFile, ecacertfile,
- erlang:get_stacktrace())
- end.
-init_certificates(CertDbRef, CacheRef, CertFile, client) ->
+init_certificates(#ssl_options{cacerts = CaCerts,
+ cacertfile = CACertFile,
+ certfile = CertFile,
+ cert = Cert}, Role) ->
+ {ok, CertDbRef, CacheRef} =
+ try
+ Certs = case CaCerts of
+ undefined ->
+ CACertFile;
+ _ ->
+ {der, CaCerts}
+ end,
+ {ok, _, _} = ssl_manager:connection_init(Certs, Role)
+ catch
+ Error:Reason ->
+ handle_file_error(?LINE, Error, Reason, CACertFile, ecacertfile,
+ erlang:get_stacktrace())
+ end,
+ init_certificates(Cert, CertDbRef, CacheRef, CertFile, Role).
+
+init_certificates(undefined, CertDbRef, CacheRef, "", _) ->
+ {ok, CertDbRef, CacheRef, undefined};
+
+init_certificates(undefined, CertDbRef, CacheRef, CertFile, client) ->
try
[OwnCert] = ssl_certificate:file_to_certificats(CertFile),
{ok, CertDbRef, CacheRef, OwnCert}
- catch _E:_R ->
+ catch _Error:_Reason ->
{ok, CertDbRef, CacheRef, undefined}
end;
-init_certificates(CertDbRef, CacheRef, CertFile, server) ->
- try
+init_certificates(undefined, CertDbRef, CacheRef, CertFile, server) ->
+ try
[OwnCert] = ssl_certificate:file_to_certificats(CertFile),
{ok, CertDbRef, CacheRef, OwnCert}
- catch
- Error:Reason ->
- handle_file_error(?LINE, Error, Reason, CertFile, ecertfile,
- erlang:get_stacktrace())
- end.
+ catch
+ Error:Reason ->
+ handle_file_error(?LINE, Error, Reason, CertFile, ecertfile,
+ erlang:get_stacktrace())
+ end;
+init_certificates(Cert, CertDbRef, CacheRef, _, _) ->
+ {ok, CertDbRef, CacheRef, Cert}.
-init_private_key(undefined, "", _Password, client) ->
+init_private_key(undefined, "", _Password, _Client) ->
undefined;
init_private_key(undefined, KeyFile, Password, _) ->
- case ssl_manager:cache_pem_file(KeyFile) of
- {ok, List} ->
- [Der] = [Der || Der = {PKey, _ , _} <- List,
- PKey =:= rsa_private_key orelse
- PKey =:= dsa_private_key],
- {ok, Decoded} = public_key:decode_private_key(Der,Password),
- Decoded;
- {error, Reason} ->
- handle_file_error(?LINE, error, Reason, KeyFile, ekeyfile,
+ try
+ {ok, List} = ssl_manager:cache_pem_file(KeyFile),
+ [PemEntry] = [PemEntry || PemEntry = {PKey, _ , _} <- List,
+ PKey =:= 'RSAPrivateKey' orelse
+ PKey =:= 'DSAPrivateKey'],
+ public_key:pem_entry_decode(PemEntry, Password)
+ catch
+ Error:Reason ->
+ handle_file_error(?LINE, Error, Reason, KeyFile, ekeyfile,
erlang:get_stacktrace())
end;
-init_private_key(PrivateKey, _, _,_) ->
- PrivateKey.
+init_private_key({rsa, PrivateKey}, _, _,_) ->
+ public_key:der_decode('RSAPrivateKey', PrivateKey);
+init_private_key({dsa, PrivateKey},_,_,_) ->
+ public_key:der_decode('DSAPrivateKey', PrivateKey).
handle_file_error(Line, Error, {badmatch, Reason}, File, Throw, Stack) ->
file_error(Line, Error, Reason, File, Throw, Stack);
handle_file_error(Line, Error, Reason, File, Throw, Stack) ->
file_error(Line, Error, Reason, File, Throw, Stack).
+-spec(file_error/6 :: (_,_,_,_,_,_) -> no_return()).
file_error(Line, Error, Reason, File, Throw, Stack) ->
Report = io_lib:format("SSL: ~p: ~p:~p ~s~n ~p~n",
[Line, Error, Reason, File, Stack]),
error_logger:error_report(Report),
throw(Throw).
-init_diffie_hellman(_, client) ->
+init_diffie_hellman(Params, _,_) when is_binary(Params)->
+ public_key:der_decode('DHParameter', Params);
+init_diffie_hellman(_,_, client) ->
undefined;
-init_diffie_hellman(undefined, _) ->
+init_diffie_hellman(_,undefined, _) ->
?DEFAULT_DIFFIE_HELLMAN_PARAMS;
-init_diffie_hellman(DHParamFile, server) ->
- case ssl_manager:cache_pem_file(DHParamFile) of
- {ok, List} ->
- case [Der || Der = {dh_params, _ , _} <- List] of
- [Der] ->
- {ok, Decoded} = public_key:decode_dhparams(Der),
- Decoded;
- [] ->
- ?DEFAULT_DIFFIE_HELLMAN_PARAMS
- end;
- {error, Reason} ->
- handle_file_error(?LINE, error, Reason, DHParamFile, edhfile, erlang:get_stacktrace())
+init_diffie_hellman(_, DHParamFile, server) ->
+ try
+ {ok, List} = ssl_manager:cache_pem_file(DHParamFile),
+ case [Entry || Entry = {'DHParameter', _ , _} <- List] of
+ [Entry] ->
+ public_key:pem_entry_decode(Entry);
+ [] ->
+ ?DEFAULT_DIFFIE_HELLMAN_PARAMS
+ end
+ catch
+ Error:Reason ->
+ handle_file_error(?LINE, Error, Reason,
+ DHParamFile, edhfile, erlang:get_stacktrace())
end.
sync_send_all_state_event(FsmPid, Event) ->
@@ -1162,23 +1167,22 @@ verify_client_cert(#state{client_certificate_requested = true, role = client,
negotiated_version = Version,
own_cert = OwnCert,
socket = Socket,
- key_algorithm = KeyAlg,
private_key = PrivateKey,
session = #session{master_secret = MasterSecret},
tls_handshake_hashes = Hashes0} = State) ->
+
case ssl_handshake:client_certificate_verify(OwnCert, MasterSecret,
- Version, KeyAlg,
- PrivateKey, Hashes0) of
+ Version, PrivateKey, Hashes0) of
#certificate_verify{} = Verified ->
{BinVerified, ConnectionStates1, Hashes1} =
- encode_handshake(Verified, KeyAlg, Version,
+ encode_handshake(Verified, Version,
ConnectionStates0, Hashes0),
Transport:send(Socket, BinVerified),
State#state{connection_states = ConnectionStates1,
tls_handshake_hashes = Hashes1};
ignore ->
State;
- #alert{} = Alert ->
+ #alert{} = Alert ->
handle_own_alert(Alert, Version, certify, State)
end;
@@ -1186,18 +1190,19 @@ verify_client_cert(#state{client_certificate_requested = false} = State) ->
State.
do_server_hello(Type, #state{negotiated_version = Version,
- session = Session,
+ session = #session{session_id = SessId} = Session,
connection_states = ConnectionStates0,
renegotiation = {Renegotiation, _}}
= State0) when is_atom(Type) ->
+
ServerHello =
- ssl_handshake:server_hello(Session#session.session_id, Version,
+ ssl_handshake:server_hello(SessId, Version,
ConnectionStates0, Renegotiation),
State1 = server_hello(ServerHello, State0),
case Type of
new ->
- do_server_hello(ServerHello, State1);
+ new_server_hello(ServerHello, State1);
resumed ->
ConnectionStates1 = State1#state.connection_states,
case ssl_handshake:master_secret(Version, Session,
@@ -1216,9 +1221,9 @@ do_server_hello(Type, #state{negotiated_version = Version,
handle_own_alert(Alert, Version, hello, State1),
{stop, normal, State1}
end
- end;
+ end.
-do_server_hello(#server_hello{cipher_suite = CipherSuite,
+new_server_hello(#server_hello{cipher_suite = CipherSuite,
compression_method = Compression,
session_id = SessionId},
#state{session = Session0,
@@ -1319,15 +1324,17 @@ server_hello_done(#state{transport_cb = Transport,
Transport:send(Socket, BinHelloDone),
State#state{connection_states = NewConnectionStates,
tls_handshake_hashes = NewHashes}.
-
-certify_server(#state{transport_cb = Transport,
- socket = Socket,
- negotiated_version = Version,
- connection_states = ConnectionStates,
- tls_handshake_hashes = Hashes,
- cert_db_ref = CertDbRef,
- own_cert = OwnCert} = State) ->
+certify_server(#state{key_algorithm = dh_anon} = State) ->
+ State;
+
+certify_server(#state{transport_cb = Transport,
+ socket = Socket,
+ negotiated_version = Version,
+ connection_states = ConnectionStates,
+ tls_handshake_hashes = Hashes,
+ cert_db_ref = CertDbRef,
+ own_cert = OwnCert} = State) ->
case ssl_handshake:certificate(OwnCert, CertDbRef, server) of
CertMsg = #certificate{} ->
{BinCertMsg, NewConnectionStates, NewHashes} =
@@ -1343,7 +1350,7 @@ certify_server(#state{transport_cb = Transport,
key_exchange(#state{role = server, key_algorithm = rsa} = State) ->
State;
key_exchange(#state{role = server, key_algorithm = Algo,
- diffie_hellman_params = Params,
+ diffie_hellman_params = #'DHParameter'{prime = P, base = G} = Params,
private_key = PrivateKey,
connection_states = ConnectionStates0,
negotiated_version = Version,
@@ -1352,9 +1359,10 @@ key_exchange(#state{role = server, key_algorithm = Algo,
transport_cb = Transport
} = State)
when Algo == dhe_dss;
- Algo == dhe_rsa ->
+ Algo == dhe_rsa;
+ Algo == dh_anon ->
- Keys = public_key:gen_key(Params),
+ Keys = crypto:dh_generate_key([crypto:mpint(P), crypto:mpint(G)]),
ConnectionState =
ssl_record:pending_connection_state(ConnectionStates0, read),
SecParams = ConnectionState#connection_state.security_parameters,
@@ -1371,11 +1379,6 @@ key_exchange(#state{role = server, key_algorithm = Algo,
diffie_hellman_keys = Keys,
tls_handshake_hashes = Hashes1};
-
-%% key_algorithm = dh_anon is not supported. Should be by default disabled
-%% if support is implemented and then we need a key_exchange clause for it
-%% here.
-
key_exchange(#state{role = client,
connection_states = ConnectionStates0,
key_algorithm = rsa,
@@ -1398,7 +1401,8 @@ key_exchange(#state{role = client,
socket = Socket, transport_cb = Transport,
tls_handshake_hashes = Hashes0} = State)
when Algorithm == dhe_dss;
- Algorithm == dhe_rsa ->
+ Algorithm == dhe_rsa;
+ Algorithm == dh_anon ->
Msg = ssl_handshake:key_exchange(client, {dh, DhPubKey}),
{BinMsg, ConnectionStates1, Hashes1} =
encode_handshake(Msg, Version, ConnectionStates0, Hashes0),
@@ -1406,6 +1410,8 @@ key_exchange(#state{role = client,
State#state{connection_states = ConnectionStates1,
tls_handshake_hashes = Hashes1}.
+-spec(rsa_key_exchange/2 :: (_,_) -> no_return()).
+
rsa_key_exchange(PremasterSecret, PublicKeyInfo = {Algorithm, _, _})
when Algorithm == ?rsaEncryption;
Algorithm == ?md2WithRSAEncryption;
@@ -1474,23 +1480,30 @@ save_verify_data(client, #finished{verify_data = Data}, ConnectionStates, abbrev
save_verify_data(server, #finished{verify_data = Data}, ConnectionStates, abbreviated) ->
ssl_record:set_server_verify_data(current_write, Data, ConnectionStates).
+handle_server_key(#server_key_exchange{params =
+ #server_dh_params{dh_p = P,
+ dh_g = G,
+ dh_y = ServerPublicDhKey},
+ signed_params = <<>>},
+ #state{key_algorithm = dh_anon} = State) ->
+ dh_master_secret(P, G, ServerPublicDhKey, undefined, State);
+
handle_server_key(
#server_key_exchange{params =
#server_dh_params{dh_p = P,
dh_g = G,
dh_y = ServerPublicDhKey},
signed_params = Signed},
- #state{session = Session, negotiated_version = Version, role = Role,
- public_key_info = PubKeyInfo,
+ #state{public_key_info = PubKeyInfo,
key_algorithm = KeyAlgo,
- connection_states = ConnectionStates0} = State) ->
+ connection_states = ConnectionStates} = State) ->
PLen = size(P),
GLen = size(G),
YLen = size(ServerPublicDhKey),
ConnectionState =
- ssl_record:pending_connection_state(ConnectionStates0, read),
+ ssl_record:pending_connection_state(ConnectionStates, read),
SecParams = ConnectionState#connection_state.security_parameters,
#security_parameters{client_random = ClientRandom,
server_random = ServerRandom} = SecParams,
@@ -1504,29 +1517,11 @@ handle_server_key(
case verify_dh_params(Signed, Hash, PubKeyInfo) of
true ->
- PMpint = mpint_binary(P),
- GMpint = mpint_binary(G),
- Keys = {_, ClientDhPrivateKey} =
- crypto:dh_generate_key([PMpint,GMpint]),
- PremasterSecret =
- crypto:dh_compute_key(mpint_binary(ServerPublicDhKey),
- ClientDhPrivateKey, [PMpint, GMpint]),
- case ssl_handshake:master_secret(Version, PremasterSecret,
- ConnectionStates0, Role) of
- {MasterSecret, ConnectionStates} ->
- State#state{diffie_hellman_keys = Keys,
- session =
- Session#session{master_secret
- = MasterSecret},
- connection_states = ConnectionStates};
- #alert{} = Alert ->
- Alert
- end;
+ dh_master_secret(P, G, ServerPublicDhKey, undefined, State);
false ->
?ALERT_REC(?FATAL,?HANDSHAKE_FAILURE)
end.
-
verify_dh_params(Signed, Hashes, {?rsaEncryption, PubKey, _PubKeyParams}) ->
case public_key:decrypt_public(Signed, PubKey,
[{rsa_pad, rsa_pkcs1_padding}]) of
@@ -1536,8 +1531,32 @@ verify_dh_params(Signed, Hashes, {?rsaEncryption, PubKey, _PubKeyParams}) ->
false
end;
verify_dh_params(Signed, Hash, {?'id-dsa', PublicKey, PublicKeyParams}) ->
- public_key:verify_signature(Hash, none, Signed, PublicKey, PublicKeyParams).
-
+ public_key:verify(Hash, none, Signed, {PublicKey, PublicKeyParams}).
+
+dh_master_secret(Prime, Base, PublicDhKey, undefined, State) ->
+ PMpint = mpint_binary(Prime),
+ GMpint = mpint_binary(Base),
+ Keys = {_, PrivateDhKey} =
+ crypto:dh_generate_key([PMpint,GMpint]),
+ dh_master_secret(PMpint, GMpint, PublicDhKey, PrivateDhKey, State#state{diffie_hellman_keys = Keys});
+
+dh_master_secret(PMpint, GMpint, PublicDhKey, PrivateDhKey,
+ #state{session = Session,
+ negotiated_version = Version, role = Role,
+ connection_states = ConnectionStates0} = State) ->
+ PremasterSecret =
+ crypto:dh_compute_key(mpint_binary(PublicDhKey), PrivateDhKey,
+ [PMpint, GMpint]),
+ case ssl_handshake:master_secret(Version, PremasterSecret,
+ ConnectionStates0, Role) of
+ {MasterSecret, ConnectionStates} ->
+ State#state{
+ session =
+ Session#session{master_secret = MasterSecret},
+ connection_states = ConnectionStates};
+ #alert{} = Alert ->
+ Alert
+ end.
cipher_role(client, Data, Session, #state{connection_states = ConnectionStates0} = State) ->
ConnectionStates = ssl_record:set_server_verify_data(current_both, Data, ConnectionStates0),
@@ -1562,13 +1581,9 @@ encode_change_cipher(#change_cipher_spec{}, Version, ConnectionStates) ->
?DBG_TERM(#change_cipher_spec{}),
ssl_record:encode_change_cipher_spec(Version, ConnectionStates).
-encode_handshake(HandshakeRec, Version, ConnectionStates, Hashes) ->
- encode_handshake(HandshakeRec, undefined, Version,
- ConnectionStates, Hashes).
-
-encode_handshake(HandshakeRec, SigAlg, Version, ConnectionStates0, Hashes0) ->
+encode_handshake(HandshakeRec, Version, ConnectionStates0, Hashes0) ->
?DBG_TERM(HandshakeRec),
- Frag = ssl_handshake:encode_handshake(HandshakeRec, Version, SigAlg),
+ Frag = ssl_handshake:encode_handshake(HandshakeRec, Version),
Hashes1 = ssl_handshake:update_hashes(Hashes0, Frag),
{E, ConnectionStates1} =
ssl_record:encode_handshake(Frag, Version, ConnectionStates0),
@@ -1626,8 +1641,6 @@ application_data(Data, #state{user_application = {_Mon, Pid},
true -> <<Buffer0/binary, Data/binary>>
end,
case get_data(SOpts, BytesToRead, Buffer1) of
- {ok, <<>>, Buffer} -> % no reply, we need more data
- next_record(State0#state{user_data_buffer = Buffer});
{ok, ClientData, Buffer} -> % Send data
SocketOpt = deliver_app_data(SOpts, ClientData, Pid, From),
State = State0#state{user_data_buffer = Buffer,
@@ -1643,12 +1656,16 @@ application_data(Data, #state{user_application = {_Mon, Pid},
true -> %% We have more data
application_data(<<>>, State)
end;
+ {more, Buffer} -> % no reply, we need more data
+ next_record(State0#state{user_data_buffer = Buffer});
{error,_Reason} -> %% Invalid packet in packet mode
deliver_packet_error(SOpts, Buffer1, Pid, From),
{stop, normal, State0}
end.
%% Picks ClientData
+get_data(_, _, <<>>) ->
+ {more, <<>>};
get_data(#socket_options{active=Active, packet=Raw}, BytesToRead, Buffer)
when Raw =:= raw; Raw =:= 0 -> %% Raw Mode
if
@@ -1661,13 +1678,13 @@ get_data(#socket_options{active=Active, packet=Raw}, BytesToRead, Buffer)
{ok, Data, Rest};
true ->
%% Passive Mode not enough data
- {ok, <<>>, Buffer}
+ {more, Buffer}
end;
get_data(#socket_options{packet=Type, packet_size=Size}, _, Buffer) ->
PacketOpts = [{packet_size, Size}],
case decode_packet(Type, Buffer, PacketOpts) of
{more, _} ->
- {ok, <<>>, Buffer};
+ {more, Buffer};
Decoded ->
Decoded
end.
@@ -1726,11 +1743,13 @@ format_packet_error(#socket_options{active = _, mode = Mode}, Data) ->
format_reply(binary, _, N, Data) when N > 0 -> % Header mode
header(N, Data);
-format_reply(binary, _, _, Data) -> Data;
-format_reply(list, Packet, _, Data) when is_integer(Packet); Packet == raw ->
- binary_to_list(Data);
+format_reply(binary, _, _, Data) ->
+ Data;
+format_reply(list, Packet, _, Data)
+ when Packet == http; Packet == {http, headers}; Packet == http_bin; Packet == {http_bin, headers} ->
+ Data;
format_reply(list, _,_, Data) ->
- Data.
+ binary_to_list(Data).
header(0, <<>>) ->
<<>>;
@@ -1780,9 +1799,7 @@ next_state(Next, #ssl_tls{type = ?ALERT, fragment = EncAlerts}, State) ->
handle_alerts(Alerts, {next_state, Next, State});
next_state(StateName, #ssl_tls{type = ?HANDSHAKE, fragment = Data},
- State0 = #state{key_algorithm = KeyAlg,
- tls_handshake_buffer = Buf0,
- negotiated_version = Version}) ->
+ State0 = #state{tls_handshake_buffer = Buf0, negotiated_version = Version}) ->
Handle =
fun({#hello_request{} = Packet, _}, {next_state, connection = SName, State}) ->
%% This message should not be included in handshake
@@ -1805,7 +1822,7 @@ next_state(StateName, #ssl_tls{type = ?HANDSHAKE, fragment = Data},
(_, StopState) -> StopState
end,
try
- {Packets, Buf} = ssl_handshake:get_tls_handshake(Data,Buf0, KeyAlg,Version),
+ {Packets, Buf} = ssl_handshake:get_tls_handshake(Data,Buf0),
State = State0#state{tls_packets = Packets, tls_handshake_buffer = Buf},
handle_tls_handshake(Handle, StateName, State)
catch throw:#alert{} = Alert ->
@@ -1817,7 +1834,7 @@ next_state(StateName, #ssl_tls{type = ?APPLICATION_DATA, fragment = Data}, State
case application_data(Data, State0) of
Stop = {stop,_,_} ->
Stop;
- {Record, State} ->
+ {Record, State} ->
next_state(StateName, Record, State)
end;
next_state(StateName, #ssl_tls{type = ?CHANGE_CIPHER_SPEC, fragment = <<1>>} =
@@ -2154,7 +2171,7 @@ renegotiate(#state{role = server,
negotiated_version = Version,
connection_states = ConnectionStates0} = State0) ->
HelloRequest = ssl_handshake:hello_request(),
- Frag = ssl_handshake:encode_handshake(HelloRequest, Version, undefined),
+ Frag = ssl_handshake:encode_handshake(HelloRequest, Version),
Hs0 = ssl_handshake:init_hashes(),
{BinMsg, ConnectionStates} =
ssl_record:encode_handshake(Frag, Version, ConnectionStates0),
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index fcc30f6137..f8e5d585e7 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -31,32 +31,32 @@
-include("ssl_debug.hrl").
-include_lib("public_key/include/public_key.hrl").
--export([master_secret/4, client_hello/6, server_hello/4, hello/4,
- hello_request/0, certify/7, certificate/3,
- client_certificate_verify/6,
- certificate_verify/6, certificate_request/2,
- key_exchange/2, server_key_exchange_hash/2, finished/4,
- verify_connection/5,
- get_tls_handshake/4,
- server_hello_done/0, sig_alg/1,
- encode_handshake/3, init_hashes/0,
- update_hashes/2, decrypt_premaster_secret/2]).
-
--type tls_handshake() :: #client_hello{} | #server_hello{} | #server_hello_done{} |
-#certificate{} | #client_key_exchange{} | #finished{} | #certificate_verify{}.
+-export([master_secret/4, client_hello/5, server_hello/4, hello/4,
+ hello_request/0, certify/6, certificate/3,
+ client_certificate_verify/5, certificate_verify/5,
+ certificate_request/2, key_exchange/2, server_key_exchange_hash/2,
+ finished/4, verify_connection/5, get_tls_handshake/2,
+ decode_client_key/3, server_hello_done/0,
+ encode_handshake/2, init_hashes/0, update_hashes/2,
+ decrypt_premaster_secret/2]).
+
+-type tls_handshake() :: #client_hello{} | #server_hello{} |
+ #server_hello_done{} | #certificate{} | #certificate_request{} |
+ #client_key_exchange{} | #finished{} | #certificate_verify{} |
+ #hello_request{}.
%%====================================================================
%% Internal application API
%%====================================================================
%%--------------------------------------------------------------------
-spec client_hello(host(), port_num(), #connection_states{},
- #ssl_options{}, binary(), boolean()) -> #client_hello{}.
+ #ssl_options{}, boolean()) -> #client_hello{}.
%%
%% Description: Creates a client hello message.
%%--------------------------------------------------------------------
client_hello(Host, Port, ConnectionStates, #ssl_options{versions = Versions,
ciphers = UserSuites}
- = SslOpts, Cert, Renegotiation) ->
+ = SslOpts, Renegotiation) ->
Fun = fun(Version) ->
ssl_record:protocol_version(Version)
@@ -64,7 +64,7 @@ client_hello(Host, Port, ConnectionStates, #ssl_options{versions = Versions,
Version = ssl_record:highest_protocol_version(lists:map(Fun, Versions)),
Pending = ssl_record:pending_connection_state(ConnectionStates, read),
SecParams = Pending#connection_state.security_parameters,
- Ciphers = available_suites(Cert, UserSuites, Version),
+ Ciphers = available_suites(UserSuites, Version),
Id = ssl_manager:client_session_id(Host, Port, SslOpts),
@@ -110,7 +110,7 @@ hello_request() ->
#connection_states{} | {port_num(), #session{}, cache_ref(),
atom(), #connection_states{}, binary()},
boolean()) -> {tls_version(), session_id(), #connection_states{}}|
- {tls_version(), {resumed | new, session_id()},
+ {tls_version(), {resumed | new, #session{}},
#connection_states{}} | #alert{}.
%%
%% Description: Handles a recieved hello message
@@ -175,64 +175,57 @@ hello(#client_hello{client_version = ClientVersion, random = Random,
%%--------------------------------------------------------------------
-spec certify(#certificate{}, term(), integer() | nolimit,
- verify_peer | verify_none, fun(), fun(),
+ verify_peer | verify_none, {fun(), term},
client | server) -> {der_cert(), public_key_info()} | #alert{}.
%%
%% Description: Handles a certificate handshake message
%%--------------------------------------------------------------------
-certify(#certificate{asn1_certificates = ASN1Certs}, CertDbRef,
- MaxPathLen, Verify, VerifyFun, ValidateFun, Role) ->
+certify(#certificate{asn1_certificates = ASN1Certs}, CertDbRef,
+ MaxPathLen, _Verify, VerifyFunAndState, Role) ->
[PeerCert | _] = ASN1Certs,
- VerifyBool = verify_bool(Verify),
- ValidateExtensionFun =
- case ValidateFun of
+ ValidationFunAndState =
+ case VerifyFunAndState of
undefined ->
- fun(Extensions, ValidationState, Verify0, AccError) ->
- ssl_certificate:validate_extensions(Extensions, ValidationState,
- [], Verify0, AccError, Role)
- end;
- Fun ->
- fun(Extensions, ValidationState, Verify0, AccError) ->
- {NewExtensions, NewValidationState, NewAccError}
- = ssl_certificate:validate_extensions(Extensions, ValidationState,
- [], Verify0, AccError, Role),
- Fun(NewExtensions, NewValidationState, Verify0, NewAccError)
- end
+ {fun(OtpCert, ExtensionOrError, SslState) ->
+ ssl_certificate:validate_extension(OtpCert,
+ ExtensionOrError, SslState)
+ end, Role};
+ {Fun, UserState0} ->
+ {fun(OtpCert, ExtensionOrError, {SslState, UserState}) ->
+ case ssl_certificate:validate_extension(OtpCert,
+ ExtensionOrError,
+ SslState) of
+ {valid, _} ->
+ apply_user_fun(Fun, OtpCert,
+ ExtensionOrError, UserState,
+ SslState);
+ {fail, Reason} ->
+ apply_user_fun(Fun, OtpCert, Reason, UserState,
+ SslState);
+ {unknown, _} ->
+ apply_user_fun(Fun, OtpCert,
+ ExtensionOrError, UserState, SslState)
+ end
+ end, {Role, UserState0}}
end,
- try
- %% Allow missing root_cert and check that with VerifyFun
- ssl_certificate:trusted_cert_and_path(ASN1Certs, CertDbRef, false) of
- {TrustedErlCert, CertPath, VerifyErrors} ->
- Result = public_key:pkix_path_validation(TrustedErlCert,
- CertPath,
- [{max_path_length,
- MaxPathLen},
- {verify, VerifyBool},
- {validate_extensions_fun,
- ValidateExtensionFun},
- {acc_errors,
- VerifyErrors}]),
- case Result of
- {error, Reason} ->
- path_validation_alert(Reason, Verify);
- {ok, {PublicKeyInfo,_, []}} ->
- {PeerCert, PublicKeyInfo};
- {ok, {PublicKeyInfo,_, AccErrors = [Error | _]}} ->
- case VerifyFun(AccErrors) of
- true ->
- {PeerCert, PublicKeyInfo};
- false ->
- path_validation_alert(Error, Verify)
- end
- end
- catch
- throw:Alert ->
- Alert
+
+ {TrustedErlCert, CertPath} =
+ ssl_certificate:trusted_cert_and_path(ASN1Certs, CertDbRef),
+
+ case public_key:pkix_path_validation(TrustedErlCert,
+ CertPath,
+ [{max_path_length,
+ MaxPathLen},
+ {verify_fun, ValidationFunAndState}]) of
+ {ok, {PublicKeyInfo,_}} ->
+ {PeerCert, PublicKeyInfo};
+ {error, Reason} ->
+ path_validation_alert(Reason)
end.
-
+
%%--------------------------------------------------------------------
--spec certificate(der_cert(), term(), client | server) -> #certificate{}.
+-spec certificate(der_cert(), term(), client | server) -> #certificate{} | #alert{}.
%%
%% Description: Creates a certificate message.
%%--------------------------------------------------------------------
@@ -244,7 +237,7 @@ certificate(OwnCert, CertDbRef, client) ->
{error, _} ->
%% If no suitable certificate is available, the client
%% SHOULD send a certificate message containing no
- %% certificates. (chapter 7.4.6. rfc 4346)
+ %% certificates. (chapter 7.4.6. RFC 4346)
[]
end,
#certificate{asn1_certificates = Chain};
@@ -259,17 +252,17 @@ certificate(OwnCert, CertDbRef, server) ->
%%--------------------------------------------------------------------
-spec client_certificate_verify(undefined | der_cert(), binary(),
- tls_version(), key_algo(), private_key(),
- {binary(), binary()}) ->
- #certificate_verify{} | ignore.
+ tls_version(), private_key(),
+ {{binary(), binary()},{binary(), binary()}}) ->
+ #certificate_verify{} | ignore | #alert{}.
%%
%% Description: Creates a certificate_verify message, called by the client.
%%--------------------------------------------------------------------
-client_certificate_verify(undefined, _, _, _, _, _) ->
+client_certificate_verify(undefined, _, _, _, _) ->
ignore;
-client_certificate_verify(_, _, _, _, undefined, _) ->
+client_certificate_verify(_, _, _, undefined, _) ->
ignore;
-client_certificate_verify(OwnCert, MasterSecret, Version, Algorithm,
+client_certificate_verify(OwnCert, MasterSecret, Version,
PrivateKey, {Hashes0, _}) ->
case public_key:pkix_is_fixed_dh_cert(OwnCert) of
true ->
@@ -277,36 +270,33 @@ client_certificate_verify(OwnCert, MasterSecret, Version, Algorithm,
false ->
Hashes =
calc_certificate_verify(Version, MasterSecret,
- Algorithm, Hashes0),
+ alg_oid(PrivateKey), Hashes0),
Signed = digitally_signed(Hashes, PrivateKey),
#certificate_verify{signature = Signed}
end.
%%--------------------------------------------------------------------
-spec certificate_verify(binary(), public_key_info(), tls_version(),
- binary(), key_algo(),
- {binary(), binary()}) -> valid | #alert{}.
+ binary(), {_, {binary(), binary()}}) -> valid | #alert{}.
%%
%% Description: Checks that the certificate_verify message is valid.
%%--------------------------------------------------------------------
-certificate_verify(Signature, {_, PublicKey, _}, Version,
- MasterSecret, Algorithm, {_, Hashes0})
- when Algorithm == rsa;
- Algorithm == dhe_rsa ->
+certificate_verify(Signature, {?'rsaEncryption'= Algorithm, PublicKey, _}, Version,
+ MasterSecret, {_, Hashes0}) ->
Hashes = calc_certificate_verify(Version, MasterSecret,
Algorithm, Hashes0),
- case public_key:decrypt_public(Signature, PublicKey,
+ case public_key:decrypt_public(Signature, PublicKey,
[{rsa_pad, rsa_pkcs1_padding}]) of
Hashes ->
valid;
_ ->
?ALERT_REC(?FATAL, ?BAD_CERTIFICATE)
end;
-certificate_verify(Signature, {_, PublicKey, PublicKeyParams}, Version,
- MasterSecret, dhe_dss = Algorithm, {_, Hashes0}) ->
+certificate_verify(Signature, {?'id-dsa' = Algorithm, PublicKey, PublicKeyParams}, Version,
+ MasterSecret, {_, Hashes0}) ->
Hashes = calc_certificate_verify(Version, MasterSecret,
Algorithm, Hashes0),
- case public_key:verify_signature(Hashes, none, Signature, PublicKey, PublicKeyParams) of
+ case public_key:verify(Hashes, none, Signature, {PublicKey, PublicKeyParams}) of
true ->
valid;
false ->
@@ -335,7 +325,7 @@ certificate_request(ConnectionStates, CertDbRef) ->
-spec key_exchange(client | server,
{premaster_secret, binary(), public_key_info()} |
{dh, binary()} |
- {dh, binary(), #'DHParameter'{}, key_algo(),
+ {dh, {binary(), binary()}, #'DHParameter'{}, key_algo(),
binary(), binary(), private_key()}) ->
#client_key_exchange{} | #server_key_exchange{}.
%%
@@ -362,15 +352,22 @@ key_exchange(server, {dh, {<<?UINT32(Len), PublicKey:Len/binary>>, _},
YLen = byte_size(PublicKey),
ServerDHParams = #server_dh_params{dh_p = PBin,
dh_g = GBin, dh_y = PublicKey},
- Hash =
- server_key_exchange_hash(KeyAlgo, <<ClientRandom/binary,
- ServerRandom/binary,
- ?UINT16(PLen), PBin/binary,
- ?UINT16(GLen), GBin/binary,
- ?UINT16(YLen), PublicKey/binary>>),
- Signed = digitally_signed(Hash, PrivateKey),
- #server_key_exchange{params = ServerDHParams,
- signed_params = Signed}.
+
+ case KeyAlgo of
+ dh_anon ->
+ #server_key_exchange{params = ServerDHParams,
+ signed_params = <<>>};
+ _ ->
+ Hash =
+ server_key_exchange_hash(KeyAlgo, <<ClientRandom/binary,
+ ServerRandom/binary,
+ ?UINT16(PLen), PBin/binary,
+ ?UINT16(GLen), GBin/binary,
+ ?UINT16(YLen), PublicKey/binary>>),
+ Signed = digitally_signed(Hash, PrivateKey),
+ #server_key_exchange{params = ServerDHParams,
+ signed_params = Signed}
+ end.
%%--------------------------------------------------------------------
-spec master_secret(tls_version(), #session{} | binary(), #connection_states{},
@@ -412,7 +409,7 @@ master_secret(Version, PremasterSecret, ConnectionStates, Role) ->
end.
%%--------------------------------------------------------------------
--spec finished(tls_version(), client | server, binary(), {binary(), binary()}) ->
+-spec finished(tls_version(), client | server, binary(), {{binary(), binary()},_}) ->
#finished{}.
%%
%% Description: Creates a handshake finished message
@@ -423,7 +420,7 @@ finished(Version, Role, MasterSecret, {Hashes, _}) -> % use the current hashes
%%--------------------------------------------------------------------
-spec verify_connection(tls_version(), #finished{}, client | server, binary(),
- {binary(), binary()}) -> verified | #alert{}.
+ {_, {binary(), binary()}}) -> verified | #alert{}.
%%
%% Description: Checks the ssl handshake finished message to verify
%% the connection.
@@ -448,60 +445,132 @@ server_hello_done() ->
#server_hello_done{}.
%%--------------------------------------------------------------------
--spec encode_handshake(tls_handshake(), tls_version(), key_algo()) -> binary().
+-spec encode_handshake(tls_handshake(), tls_version()) -> iolist().
%%
%% Description: Encode a handshake packet to binary
%%--------------------------------------------------------------------
-encode_handshake(Package, Version, KeyAlg) ->
- SigAlg = sig_alg(KeyAlg),
- {MsgType, Bin} = enc_hs(Package, Version, SigAlg),
+encode_handshake(Package, Version) ->
+ {MsgType, Bin} = enc_hs(Package, Version),
Len = byte_size(Bin),
[MsgType, ?uint24(Len), Bin].
%%--------------------------------------------------------------------
--spec get_tls_handshake(binary(), binary(), key_algo(), tls_version()) ->
- {[tls_handshake()], [binary()], binary()}.
+-spec get_tls_handshake(binary(), binary() | iolist()) ->
+ {[tls_handshake()], binary()}.
%%
%% Description: Given buffered and new data from ssl_record, collects
%% and returns it as a list of handshake messages, also returns leftover
%% data.
%%--------------------------------------------------------------------
-get_tls_handshake(Data, <<>>, KeyAlg, Version) ->
- get_tls_handshake_aux(Data, KeyAlg, Version, []);
-get_tls_handshake(Data, Buffer, KeyAlg, Version) ->
- get_tls_handshake_aux(list_to_binary([Buffer, Data]),
- KeyAlg, Version, []).
+get_tls_handshake(Data, <<>>) ->
+ get_tls_handshake_aux(Data, []);
+get_tls_handshake(Data, Buffer) ->
+ get_tls_handshake_aux(list_to_binary([Buffer, Data]), []).
+
+%%--------------------------------------------------------------------
+-spec decode_client_key(binary(), key_algo(), tls_version()) ->
+ #encrypted_premaster_secret{} | #client_diffie_hellman_public{}.
+%%
+%% Description: Decode client_key data and return appropriate type
+%%--------------------------------------------------------------------
+decode_client_key(ClientKey, Type, Version) ->
+ dec_client_key(ClientKey, key_exchange_alg(Type), Version).
+
+%%--------------------------------------------------------------------
+-spec init_hashes() ->{{binary(), binary()}, {binary(), binary()}}.
+
+%%
+%% Description: Calls crypto hash (md5 and sha) init functions to
+%% initalize the hash context.
+%%--------------------------------------------------------------------
+init_hashes() ->
+ T = {crypto:md5_init(), crypto:sha_init()},
+ {T, T}.
+
+%%--------------------------------------------------------------------
+-spec update_hashes({{binary(), binary()}, {binary(), binary()}}, Data ::term()) ->
+ {{binary(), binary()}, {binary(), binary()}}.
+%%
+%% Description: Calls crypto hash (md5 and sha) update functions to
+%% update the hash context with Data.
+%%--------------------------------------------------------------------
+update_hashes(Hashes, % special-case SSL2 client hello
+ <<?CLIENT_HELLO, ?UINT24(_), ?BYTE(Major), ?BYTE(Minor),
+ ?UINT16(CSLength), ?UINT16(0),
+ ?UINT16(CDLength),
+ CipherSuites:CSLength/binary,
+ ChallengeData:CDLength/binary>>) ->
+ update_hashes(Hashes,
+ <<?CLIENT_HELLO, ?BYTE(Major), ?BYTE(Minor),
+ ?UINT16(CSLength), ?UINT16(0),
+ ?UINT16(CDLength),
+ CipherSuites:CSLength/binary,
+ ChallengeData:CDLength/binary>>);
+update_hashes({{MD50, SHA0}, _Prev}, Data) ->
+ ?DBG_HEX(Data),
+ {MD51, SHA1} = {crypto:md5_update(MD50, Data),
+ crypto:sha_update(SHA0, Data)},
+ ?DBG_HEX(crypto:md5_final(MD51)),
+ ?DBG_HEX(crypto:sha_final(SHA1)),
+ {{MD51, SHA1}, {MD50, SHA0}}.
+
+%%--------------------------------------------------------------------
+-spec decrypt_premaster_secret(binary(), #'RSAPrivateKey'{}) -> binary().
+
+%%
+%% Description: Public key decryption using the private key.
+%%--------------------------------------------------------------------
+decrypt_premaster_secret(Secret, RSAPrivateKey) ->
+ try public_key:decrypt_private(Secret, RSAPrivateKey,
+ [{rsa_pad, rsa_pkcs1_padding}])
+ catch
+ _:_ ->
+ throw(?ALERT_REC(?FATAL, ?DECRYPTION_FAILED))
+ end.
+
+%%--------------------------------------------------------------------
+-spec server_key_exchange_hash(rsa | dhe_rsa| dhe_dss | dh_anon, binary()) -> binary().
+
+%%
+%% Description: Calculate server key exchange hash
+%%--------------------------------------------------------------------
+server_key_exchange_hash(Algorithm, Value) when Algorithm == rsa;
+ Algorithm == dhe_rsa ->
+ MD5 = crypto:md5(Value),
+ SHA = crypto:sha(Value),
+ <<MD5/binary, SHA/binary>>;
+
+server_key_exchange_hash(dhe_dss, Value) ->
+ crypto:sha(Value).
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
get_tls_handshake_aux(<<?BYTE(Type), ?UINT24(Length),
- Body:Length/binary,Rest/binary>>, KeyAlg,
- Version, Acc) ->
+ Body:Length/binary,Rest/binary>>, Acc) ->
Raw = <<?BYTE(Type), ?UINT24(Length), Body/binary>>,
- H = dec_hs(Type, Body, key_exchange_alg(KeyAlg), Version),
- get_tls_handshake_aux(Rest, KeyAlg, Version, [{H,Raw} | Acc]);
-get_tls_handshake_aux(Data, _KeyAlg, _Version, Acc) ->
+ H = dec_hs(Type, Body),
+ get_tls_handshake_aux(Rest, [{H,Raw} | Acc]);
+get_tls_handshake_aux(Data, Acc) ->
{lists:reverse(Acc), Data}.
-verify_bool(verify_peer) ->
- true;
-verify_bool(verify_none) ->
- false.
-
-path_validation_alert({bad_cert, cert_expired}, _) ->
+path_validation_alert({bad_cert, cert_expired}) ->
?ALERT_REC(?FATAL, ?CERTIFICATE_EXPIRED);
-path_validation_alert({bad_cert, invalid_issuer}, _) ->
+path_validation_alert({bad_cert, invalid_issuer}) ->
?ALERT_REC(?FATAL, ?BAD_CERTIFICATE);
-path_validation_alert({bad_cert, invalid_signature} , _) ->
+path_validation_alert({bad_cert, invalid_signature}) ->
?ALERT_REC(?FATAL, ?BAD_CERTIFICATE);
-path_validation_alert({bad_cert, name_not_permitted}, _) ->
+path_validation_alert({bad_cert, name_not_permitted}) ->
?ALERT_REC(?FATAL, ?BAD_CERTIFICATE);
-path_validation_alert({bad_cert, unknown_critical_extension}, _) ->
+path_validation_alert({bad_cert, unknown_critical_extension}) ->
?ALERT_REC(?FATAL, ?UNSUPPORTED_CERTIFICATE);
-path_validation_alert({bad_cert, cert_revoked}, _) ->
+path_validation_alert({bad_cert, cert_revoked}) ->
?ALERT_REC(?FATAL, ?CERTIFICATE_REVOKED);
-path_validation_alert(_, _) ->
+path_validation_alert({bad_cert, selfsigned_peer}) ->
+ ?ALERT_REC(?FATAL, ?BAD_CERTIFICATE);
+path_validation_alert({bad_cert, unknown_ca}) ->
+ ?ALERT_REC(?FATAL, ?UNKNOWN_CA);
+path_validation_alert(_) ->
?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE).
select_session(Hello, Port, Session, Version,
@@ -524,13 +593,16 @@ select_session(Hello, Port, Session, Version,
{resumed, CacheCb:lookup(Cache, {Port, SessionId})}
end.
-available_suites(Cert, UserSuites, Version) ->
+available_suites(UserSuites, Version) ->
case UserSuites of
[] ->
- ssl_cipher:filter(Cert, ssl_cipher:suites(Version));
+ ssl_cipher:suites(Version);
_ ->
- ssl_cipher:filter(Cert, UserSuites)
+ UserSuites
end.
+
+available_suites(ServerCert, UserSuites, Version) ->
+ ssl_cipher:filter(ServerCert, available_suites(UserSuites, Version)).
cipher_suites(Suites, false) ->
[?TLS_EMPTY_RENEGOTIATION_INFO_SCSV | Suites];
@@ -724,7 +796,7 @@ master_secret(Version, MasterSecret, #security_parameters{
ServerCipherState, Role)}.
-dec_hs(?HELLO_REQUEST, <<>>, _, _) ->
+dec_hs(?HELLO_REQUEST, <<>>) ->
#hello_request{};
%% Client hello v2.
@@ -734,8 +806,7 @@ dec_hs(?CLIENT_HELLO, <<?BYTE(Major), ?BYTE(Minor),
?UINT16(CSLength), ?UINT16(0),
?UINT16(CDLength),
CipherSuites:CSLength/binary,
- ChallengeData:CDLength/binary>>,
- _, _) ->
+ ChallengeData:CDLength/binary>>) ->
?DBG_HEX(CipherSuites),
?DBG_HEX(CipherSuites),
#client_hello{client_version = {Major, Minor},
@@ -749,8 +820,7 @@ dec_hs(?CLIENT_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary,
?BYTE(SID_length), Session_ID:SID_length/binary,
?UINT16(Cs_length), CipherSuites:Cs_length/binary,
?BYTE(Cm_length), Comp_methods:Cm_length/binary,
- Extensions/binary>>,
- _, _) ->
+ Extensions/binary>>) ->
RenegotiationInfo = proplists:get_value(renegotiation_info, dec_hello_extensions(Extensions),
undefined),
@@ -765,7 +835,7 @@ dec_hs(?CLIENT_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary,
dec_hs(?SERVER_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary,
?BYTE(SID_length), Session_ID:SID_length/binary,
- Cipher_suite:2/binary, ?BYTE(Comp_method)>>, _, _) ->
+ Cipher_suite:2/binary, ?BYTE(Comp_method)>>) ->
#server_hello{
server_version = {Major,Minor},
random = Random,
@@ -777,7 +847,7 @@ dec_hs(?SERVER_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary,
dec_hs(?SERVER_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary,
?BYTE(SID_length), Session_ID:SID_length/binary,
Cipher_suite:2/binary, ?BYTE(Comp_method),
- ?UINT16(ExtLen), Extensions:ExtLen/binary>>, _, _) ->
+ ?UINT16(ExtLen), Extensions:ExtLen/binary>>) ->
RenegotiationInfo = proplists:get_value(renegotiation_info, dec_hello_extensions(Extensions, []),
undefined),
@@ -788,44 +858,49 @@ dec_hs(?SERVER_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary,
cipher_suite = Cipher_suite,
compression_method = Comp_method,
renegotiation_info = RenegotiationInfo};
-dec_hs(?CERTIFICATE, <<?UINT24(ACLen), ASN1Certs:ACLen/binary>>, _, _) ->
+dec_hs(?CERTIFICATE, <<?UINT24(ACLen), ASN1Certs:ACLen/binary>>) ->
#certificate{asn1_certificates = certs_to_list(ASN1Certs)};
dec_hs(?SERVER_KEY_EXCHANGE, <<?UINT16(PLen), P:PLen/binary,
?UINT16(GLen), G:GLen/binary,
?UINT16(YLen), Y:YLen/binary,
- ?UINT16(Len), Sig:Len/binary>>,
- ?KEY_EXCHANGE_DIFFIE_HELLMAN, _) ->
+ ?UINT16(0)>>) -> %% May happen if key_algorithm is dh_anon
+ #server_key_exchange{params = #server_dh_params{dh_p = P,dh_g = G,
+ dh_y = Y},
+ signed_params = <<>>};
+dec_hs(?SERVER_KEY_EXCHANGE, <<?UINT16(PLen), P:PLen/binary,
+ ?UINT16(GLen), G:GLen/binary,
+ ?UINT16(YLen), Y:YLen/binary,
+ ?UINT16(Len), Sig:Len/binary>>) ->
#server_key_exchange{params = #server_dh_params{dh_p = P,dh_g = G,
dh_y = Y},
signed_params = Sig};
dec_hs(?CERTIFICATE_REQUEST,
<<?BYTE(CertTypesLen), CertTypes:CertTypesLen/binary,
- ?UINT16(CertAuthsLen), CertAuths:CertAuthsLen/binary>>, _, _) ->
+ ?UINT16(CertAuthsLen), CertAuths:CertAuthsLen/binary>>) ->
#certificate_request{certificate_types = CertTypes,
certificate_authorities = CertAuths};
-dec_hs(?SERVER_HELLO_DONE, <<>>, _, _) ->
+dec_hs(?SERVER_HELLO_DONE, <<>>) ->
#server_hello_done{};
-dec_hs(?CERTIFICATE_VERIFY,<<?UINT16(_), Signature/binary>>, _, _)->
+dec_hs(?CERTIFICATE_VERIFY,<<?UINT16(_), Signature/binary>>)->
#certificate_verify{signature = Signature};
-dec_hs(?CLIENT_KEY_EXCHANGE, PKEPMS, ?KEY_EXCHANGE_RSA, {3, 0}) ->
- PreSecret = #encrypted_premaster_secret{premaster_secret = PKEPMS},
- #client_key_exchange{exchange_keys = PreSecret};
-dec_hs(?CLIENT_KEY_EXCHANGE, <<?UINT16(_), PKEPMS/binary>>,
- ?KEY_EXCHANGE_RSA, _) ->
- PreSecret = #encrypted_premaster_secret{premaster_secret = PKEPMS},
- #client_key_exchange{exchange_keys = PreSecret};
-dec_hs(?CLIENT_KEY_EXCHANGE, <<>>, ?KEY_EXCHANGE_DIFFIE_HELLMAN, _) ->
- throw(?ALERT_REC(?FATAL, ?UNSUPPORTED_CERTIFICATE));
-dec_hs(?CLIENT_KEY_EXCHANGE, <<?UINT16(DH_YLen), DH_Y:DH_YLen/binary>>,
- ?KEY_EXCHANGE_DIFFIE_HELLMAN, _) ->
- #client_key_exchange{exchange_keys =
- #client_diffie_hellman_public{dh_public = DH_Y}};
-dec_hs(?FINISHED, VerifyData, _, _) ->
+dec_hs(?CLIENT_KEY_EXCHANGE, PKEPMS) ->
+ #client_key_exchange{exchange_keys = PKEPMS};
+dec_hs(?FINISHED, VerifyData) ->
#finished{verify_data = VerifyData};
-dec_hs(_, _, _, _) ->
+dec_hs(_, _) ->
throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE)).
+dec_client_key(PKEPMS, ?KEY_EXCHANGE_RSA, {3, 0}) ->
+ #encrypted_premaster_secret{premaster_secret = PKEPMS};
+dec_client_key(<<?UINT16(_), PKEPMS/binary>>, ?KEY_EXCHANGE_RSA, _) ->
+ #encrypted_premaster_secret{premaster_secret = PKEPMS};
+dec_client_key(<<>>, ?KEY_EXCHANGE_DIFFIE_HELLMAN, _) ->
+ throw(?ALERT_REC(?FATAL, ?UNSUPPORTED_CERTIFICATE));
+dec_client_key(<<?UINT16(DH_YLen), DH_Y:DH_YLen/binary>>,
+ ?KEY_EXCHANGE_DIFFIE_HELLMAN, _) ->
+ #client_diffie_hellman_public{dh_public = DH_Y}.
+
dec_hello_extensions(<<>>) ->
[];
dec_hello_extensions(<<?UINT16(ExtLen), Extensions:ExtLen/binary>>) ->
@@ -863,14 +938,6 @@ encrypted_premaster_secret(Secret, RSAPublicKey) ->
throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE))
end.
-decrypt_premaster_secret(Secret, RSAPrivateKey) ->
- try public_key:decrypt_private(Secret, RSAPrivateKey,
- [{rsa_pad, rsa_pkcs1_padding}])
- catch
- _:_ ->
- throw(?ALERT_REC(?FATAL, ?DECRYPTION_FAILED))
- end.
-
%% encode/decode stream of certificate data to/from list of certificate data
certs_to_list(ASN1Certs) ->
certs_to_list(ASN1Certs, []).
@@ -886,14 +953,14 @@ certs_from_list(ACList) ->
<<?UINT24(CertLen), Cert/binary>>
end || Cert <- ACList]).
-enc_hs(#hello_request{}, _Version, _) ->
+enc_hs(#hello_request{}, _Version) ->
{?HELLO_REQUEST, <<>>};
enc_hs(#client_hello{client_version = {Major, Minor},
random = Random,
session_id = SessionID,
cipher_suites = CipherSuites,
compression_methods = CompMethods,
- renegotiation_info = RenegotiationInfo}, _Version, _) ->
+ renegotiation_info = RenegotiationInfo}, _Version) ->
SIDLength = byte_size(SessionID),
BinCompMethods = list_to_binary(CompMethods),
CmLength = byte_size(BinCompMethods),
@@ -911,20 +978,20 @@ enc_hs(#server_hello{server_version = {Major, Minor},
session_id = Session_ID,
cipher_suite = Cipher_suite,
compression_method = Comp_method,
- renegotiation_info = RenegotiationInfo}, _Version, _) ->
+ renegotiation_info = RenegotiationInfo}, _Version) ->
SID_length = byte_size(Session_ID),
Extensions = hello_extensions(RenegotiationInfo),
ExtensionsBin = enc_hello_extensions(Extensions),
{?SERVER_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary,
?BYTE(SID_length), Session_ID/binary,
Cipher_suite/binary, ?BYTE(Comp_method), ExtensionsBin/binary>>};
-enc_hs(#certificate{asn1_certificates = ASN1CertList}, _Version, _) ->
+enc_hs(#certificate{asn1_certificates = ASN1CertList}, _Version) ->
ASN1Certs = certs_from_list(ASN1CertList),
ACLen = erlang:iolist_size(ASN1Certs),
{?CERTIFICATE, <<?UINT24(ACLen), ASN1Certs:ACLen/binary>>};
enc_hs(#server_key_exchange{params = #server_dh_params{
dh_p = P, dh_g = G, dh_y = Y},
- signed_params = SignedParams}, _Version, _) ->
+ signed_params = SignedParams}, _Version) ->
PLen = byte_size(P),
GLen = byte_size(G),
YLen = byte_size(Y),
@@ -936,21 +1003,21 @@ enc_hs(#server_key_exchange{params = #server_dh_params{
};
enc_hs(#certificate_request{certificate_types = CertTypes,
certificate_authorities = CertAuths},
- _Version, _) ->
+ _Version) ->
CertTypesLen = byte_size(CertTypes),
CertAuthsLen = byte_size(CertAuths),
{?CERTIFICATE_REQUEST,
<<?BYTE(CertTypesLen), CertTypes/binary,
?UINT16(CertAuthsLen), CertAuths/binary>>
};
-enc_hs(#server_hello_done{}, _Version, _) ->
+enc_hs(#server_hello_done{}, _Version) ->
{?SERVER_HELLO_DONE, <<>>};
-enc_hs(#client_key_exchange{exchange_keys = ExchangeKeys}, Version, _) ->
+enc_hs(#client_key_exchange{exchange_keys = ExchangeKeys}, Version) ->
{?CLIENT_KEY_EXCHANGE, enc_cke(ExchangeKeys, Version)};
-enc_hs(#certificate_verify{signature = BinSig}, _, _) ->
+enc_hs(#certificate_verify{signature = BinSig}, _) ->
EncSig = enc_bin_sig(BinSig),
{?CERTIFICATE_VERIFY, EncSig};
-enc_hs(#finished{verify_data = VerifyData}, _Version, _) ->
+enc_hs(#finished{verify_data = VerifyData}, _Version) ->
{?FINISHED, VerifyData}.
enc_cke(#encrypted_premaster_secret{premaster_secret = PKEPMS},{3, 0}) ->
@@ -989,29 +1056,6 @@ enc_hello_extensions([#renegotiation_info{renegotiated_connection = Info} | Rest
Len = InfoLen +1,
enc_hello_extensions(Rest, <<?UINT16(?RENEGOTIATION_EXT), ?UINT16(Len), ?BYTE(InfoLen), Info/binary, Acc/binary>>).
-init_hashes() ->
- T = {crypto:md5_init(), crypto:sha_init()},
- {T, T}.
-
-update_hashes(Hashes, % special-case SSL2 client hello
- <<?CLIENT_HELLO, ?UINT24(_), ?BYTE(Major), ?BYTE(Minor),
- ?UINT16(CSLength), ?UINT16(0),
- ?UINT16(CDLength),
- CipherSuites:CSLength/binary,
- ChallengeData:CDLength/binary>>) ->
- update_hashes(Hashes,
- <<?CLIENT_HELLO, ?BYTE(Major), ?BYTE(Minor),
- ?UINT16(CSLength), ?UINT16(0),
- ?UINT16(CDLength),
- CipherSuites:CSLength/binary,
- ChallengeData:CDLength/binary>>);
-update_hashes({{MD50, SHA0}, _Prev}, Data) ->
- ?DBG_HEX(Data),
- {MD51, SHA1} = {crypto:md5_update(MD50, Data),
- crypto:sha_update(SHA0, Data)},
- ?DBG_HEX(crypto:md5_final(MD51)),
- ?DBG_HEX(crypto:sha_final(SHA1)),
- {{MD51, SHA1}, {MD50, SHA0}}.
from_3bytes(Bin3) ->
from_3bytes(Bin3, []).
@@ -1042,9 +1086,10 @@ certificate_authorities(CertDbRef) ->
Authorities = certificate_authorities_from_db(CertDbRef),
Enc = fun(#'OTPCertificate'{tbsCertificate=TBSCert}) ->
OTPSubj = TBSCert#'OTPTBSCertificate'.subject,
- Subj = public_key:pkix_transform(OTPSubj, encode),
- {ok, DNEncoded} = 'OTP-PUB-KEY':encode('Name', Subj),
- DNEncodedBin = iolist_to_binary(DNEncoded),
+ DNEncodedBin = public_key:pkix_encode('Name', OTPSubj, otp),
+ %%Subj = public_key:pkix_transform(OTPSubj, encode),
+ %% {ok, DNEncoded} = 'OTP-PUB-KEY':encode('Name', Subj),
+ %% DNEncodedBin = iolist_to_binary(DNEncoded),
DNEncodedLen = byte_size(DNEncodedBin),
<<?UINT16(DNEncodedLen), DNEncodedBin/binary>>
end,
@@ -1068,7 +1113,7 @@ digitally_signed(Hash, #'RSAPrivateKey'{} = Key) ->
public_key:encrypt_private(Hash, Key,
[{rsa_pad, rsa_pkcs1_padding}]);
digitally_signed(Hash, #'DSAPrivateKey'{} = Key) ->
- public_key:sign(none, Hash, Key).
+ public_key:sign(Hash, none, Key).
calc_master_secret({3,0}, PremasterSecret, ClientRandom, ServerRandom) ->
ssl_ssl3:master_secret(PremasterSecret, ClientRandom, ServerRandom);
@@ -1099,24 +1144,6 @@ calc_certificate_verify({3, N}, _, Algorithm, Hashes)
when N == 1; N == 2 ->
ssl_tls1:certificate_verify(Algorithm, Hashes).
-server_key_exchange_hash(Algorithm, Value) when Algorithm == rsa;
- Algorithm == dhe_rsa ->
- MD5 = crypto:md5(Value),
- SHA = crypto:sha(Value),
- <<MD5/binary, SHA/binary>>;
-
-server_key_exchange_hash(dhe_dss, Value) ->
- crypto:sha(Value).
-
-sig_alg(dh_anon) ->
- ?SIGNATURE_ANONYMOUS;
-sig_alg(Alg) when Alg == dhe_rsa; Alg == rsa ->
- ?SIGNATURE_RSA;
-sig_alg(dhe_dss) ->
- ?SIGNATURE_DSA;
-sig_alg(_) ->
- ?NULL.
-
key_exchange_alg(rsa) ->
?KEY_EXCHANGE_RSA;
key_exchange_alg(Alg) when Alg == dhe_rsa; Alg == dhe_dss;
@@ -1124,3 +1151,18 @@ key_exchange_alg(Alg) when Alg == dhe_rsa; Alg == dhe_dss;
?KEY_EXCHANGE_DIFFIE_HELLMAN;
key_exchange_alg(_) ->
?NULL.
+
+apply_user_fun(Fun, OtpCert, ExtensionOrError, UserState0, SslState) ->
+ case Fun(OtpCert, ExtensionOrError, UserState0) of
+ {valid, UserState} ->
+ {valid, {SslState, UserState}};
+ {fail, _} = Fail ->
+ Fail;
+ {unknown, UserState} ->
+ {unknown, {SslState, UserState}}
+ end.
+
+alg_oid(#'RSAPrivateKey'{}) ->
+ ?'rsaEncryption';
+alg_oid(#'DSAPrivateKey'{}) ->
+ ?'id-dsa'.
diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl
index ddace02dea..4148032cb7 100644
--- a/lib/ssl/src/ssl_internal.hrl
+++ b/lib/ssl/src/ssl_internal.hrl
@@ -63,10 +63,13 @@
validate_extensions_fun,
depth, % integer()
certfile, % file()
+ cert, % der_encoded()
keyfile, % file()
- key, %
+ key, % der_encoded()
password, %
+ cacerts, % [der_encoded()]
cacertfile, % file()
+ dh, % der_encoded()
dhfile, % file()
ciphers, %
%% Local policy for the server if it want's to reuse the session
@@ -96,16 +99,16 @@
-type from() :: term().
-type host() :: string() | tuple().
-type port_num() :: integer().
--type session_id() :: binary().
+-type session_id() :: 0 | binary().
-type tls_version() :: {integer(), integer()}.
-type tls_atom_version() :: sslv3 | tlsv1.
-type cache_ref() :: term().
-type certdb_ref() :: term().
--type key_algo() :: rsa | dhe_rsa | dhe_dss.
--type enum_algo() :: integer().
+-type key_algo() :: null | rsa | dhe_rsa | dhe_dss | dh_anon.
+-type oid() :: tuple().
-type public_key() :: #'RSAPublicKey'{} | integer().
-type public_key_params() :: #'Dss-Parms'{} | term().
--type public_key_info() :: {enum_algo(), public_key(), public_key_params()}.
+-type public_key_info() :: {oid(), public_key(), public_key_params()}.
-type der_cert() :: binary().
-type private_key() :: #'RSAPrivateKey'{} | #'DSAPrivateKey'{}.
-type issuer() :: tuple().
diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl
index af30f78dbf..3b02d96562 100644
--- a/lib/ssl/src/ssl_manager.erl
+++ b/lib/ssl/src/ssl_manager.erl
@@ -29,7 +29,8 @@
%% Internal application API
-export([start_link/1,
connection_init/2, cache_pem_file/1,
- lookup_trusted_cert/3, issuer_candidate/1, client_session_id/3, server_session_id/3,
+ lookup_trusted_cert/3, issuer_candidate/1, client_session_id/3,
+ server_session_id/3,
register_session/2, register_session/3, invalidate_session/2,
invalidate_session/3]).
@@ -68,12 +69,12 @@ start_link(Opts) ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [Opts], []).
%%--------------------------------------------------------------------
--spec connection_init(string(), client | server) -> {ok, reference(), cache_ref()}.
+-spec connection_init(string()| {der, list()}, client | server) -> {ok, reference(), cache_ref()}.
%%
%% Description: Do necessary initializations for a new connection.
%%--------------------------------------------------------------------
-connection_init(TrustedcertsFile, Role) ->
- call({connection_init, TrustedcertsFile, Role}).
+connection_init(Trustedcerts, Role) ->
+ call({connection_init, Trustedcerts, Role}).
%%--------------------------------------------------------------------
-spec cache_pem_file(string()) -> {ok, term()}.
%%
@@ -88,14 +89,17 @@ cache_pem_file(File) ->
end.
%%--------------------------------------------------------------------
-spec lookup_trusted_cert(reference(), serialnumber(), issuer()) ->
- {der_cert(), #'OTPCertificate'{}}.
+ undefined |
+ {ok, {der_cert(), #'OTPCertificate'{}}}.
%%
-%% Description: Lookup the trusted cert with Key = {reference(), serialnumber(), issuer()}.
-%%--------------------------------------------------------------------
+%% Description: Lookup the trusted cert with Key = {reference(),
+%% serialnumber(), issuer()}.
+%% --------------------------------------------------------------------
lookup_trusted_cert(Ref, SerialNumber, Issuer) ->
ssl_certificate_db:lookup_trusted_cert(Ref, SerialNumber, Issuer).
%%--------------------------------------------------------------------
--spec issuer_candidate(cert_key()) -> {cert_key(), der_cert()} | no_more_candidates.
+-spec issuer_candidate(cert_key() | no_candidate) ->
+ {cert_key(), {der_cert(), #'OTPCertificate'{}}} | no_more_candidates.
%%
%% Description: Return next issuer candidate.
%%--------------------------------------------------------------------
@@ -118,6 +122,7 @@ server_session_id(Port, SuggestedSessionId, SslOpts) ->
call({server_session_id, Port, SuggestedSessionId, SslOpts}).
%%--------------------------------------------------------------------
+-spec register_session(port_num(), #session{}) -> ok.
-spec register_session(host(), port_num(), #session{}) -> ok.
%%
%% Description: Make the session available for reuse.
@@ -128,6 +133,7 @@ register_session(Host, Port, Session) ->
register_session(Port, Session) ->
cast({register_session, Port, Session}).
%%--------------------------------------------------------------------
+-spec invalidate_session(port_num(), #session{}) -> ok.
-spec invalidate_session(host(), port_num(), #session{}) -> ok.
%%
%% Description: Make the session unavilable for reuse.
@@ -143,8 +149,9 @@ invalidate_session(Port, Session) ->
%%====================================================================
%%--------------------------------------------------------------------
--spec init(list()) -> {ok, #state{}} | {ok, #state{}, timeout()} |
- ignore | {stop, term()}.
+-spec init(list()) -> {ok, #state{}}.
+%% Possible return values not used now.
+%% | {ok, #state{}, timeout()} | ignore | {stop, term()}.
%%
%% Description: Initiates the server
%%--------------------------------------------------------------------
@@ -164,12 +171,13 @@ init([Opts]) ->
session_validation_timer = Timer}}.
%%--------------------------------------------------------------------
--spec handle_call(msg(), from(), #state{}) -> {reply, reply(), #state{}} |
- {reply, reply(), #state{}, timeout()} |
- {noreply, #state{}} |
- {noreply, #state{}, timeout()} |
- {stop, reason(), reply(), #state{}} |
- {stop, reason(), #state{}}.
+-spec handle_call(msg(), from(), #state{}) -> {reply, reply(), #state{}}.
+%% Possible return values not used now.
+%% {reply, reply(), #state{}, timeout()} |
+%% {noreply, #state{}} |
+%% {noreply, #state{}, timeout()} |
+%% {stop, reason(), reply(), #state{}} |
+%% {stop, reason(), #state{}}.
%%
%% Description: Handling call messages
%%--------------------------------------------------------------------
@@ -179,13 +187,13 @@ handle_call({{connection_init, "", _Role}, Pid}, _From,
Result = {ok, make_ref(), Cache},
{reply, Result, State};
-handle_call({{connection_init, TrustedcertsFile, _Role}, Pid}, _From,
+handle_call({{connection_init, Trustedcerts, _Role}, Pid}, _From,
#state{certificate_db = Db,
session_cache = Cache} = State) ->
erlang:monitor(process, Pid),
Result =
try
- {ok, Ref} = ssl_certificate_db:add_trusted_certs(Pid, TrustedcertsFile, Db),
+ {ok, Ref} = ssl_certificate_db:add_trusted_certs(Pid, Trustedcerts, Db),
{ok, Ref, Cache}
catch
_:Reason ->
@@ -216,9 +224,10 @@ handle_call({{cache_pem, File},Pid}, _, State = #state{certificate_db = Db}) ->
{reply, {error, Reason}, State}
end.
%%--------------------------------------------------------------------
--spec handle_cast(msg(), #state{}) -> {noreply, #state{}} |
- {noreply, #state{}, timeout()} |
- {stop, reason(), #state{}}.
+-spec handle_cast(msg(), #state{}) -> {noreply, #state{}}.
+%% Possible return values not used now.
+%% | {noreply, #state{}, timeout()} |
+%% {stop, reason(), #state{}}.
%%
%% Description: Handling cast messages
%%--------------------------------------------------------------------
@@ -253,9 +262,10 @@ handle_cast({invalidate_session, Port, #session{session_id = ID}},
{noreply, State}.
%%--------------------------------------------------------------------
--spec handle_info(msg(), #state{}) -> {noreply, #state{}} |
- {noreply, #state{}, timeout()} |
- {stop, reason(), #state{}}.
+-spec handle_info(msg(), #state{}) -> {noreply, #state{}}.
+%% Possible return values not used now.
+%% |{noreply, #state{}, timeout()} |
+%% {stop, reason(), #state{}}.
%%
%% Description: Handling all non call/cast messages
%%--------------------------------------------------------------------
diff --git a/lib/ssl/src/ssl_record.erl b/lib/ssl/src/ssl_record.erl
index 90615c22a1..803baeb09c 100644
--- a/lib/ssl/src/ssl_record.erl
+++ b/lib/ssl/src/ssl_record.erl
@@ -149,7 +149,7 @@ set_mac_secret(ReadMacSecret, WriteMacSecret,
%%--------------------------------------------------------------------
--spec set_master_secret(binary(), #connection_state{}) -> #connection_states{}.
+-spec set_master_secret(binary(), #connection_states{}) -> #connection_states{}.
%%
%% Description: Set master_secret in pending connection states
%%--------------------------------------------------------------------
@@ -306,7 +306,7 @@ set_pending_cipher_state(#connection_states{pending_read = Read,
pending_write = Write#connection_state{cipher_state = ClientState}}.
%%--------------------------------------------------------------------
--spec get_tls_records(binary(), binary()) -> {[binary()], binary()}.
+-spec get_tls_records(binary(), binary()) -> {[binary()], binary()} | #alert{}.
%%
%% Description: Given old buffer and new data from TCP, packs up a records
%% and returns it as a list of tls_compressed binaries also returns leftover
@@ -372,7 +372,8 @@ get_tls_records_aux(Data, Acc) ->
{lists:reverse(Acc), Data}.
%%--------------------------------------------------------------------
--spec protocol_version(tls_atom_version()) -> tls_version().
+-spec protocol_version(tls_atom_version() | tls_version()) ->
+ tls_version() | tls_atom_version().
%%
%% Description: Creates a protocol version record from a version atom
%% or vice versa.
@@ -467,7 +468,7 @@ is_acceptable_version(_) ->
false.
%%--------------------------------------------------------------------
--spec compressions() -> binary().
+-spec compressions() -> [binary()].
%%
%% Description: return a list of compressions supported (currently none)
%%--------------------------------------------------------------------
@@ -476,7 +477,7 @@ compressions() ->
%%--------------------------------------------------------------------
-spec decode_cipher_text(#ssl_tls{}, #connection_states{}) ->
- {#ssl_tls{}, #connection_states{}}.
+ {#ssl_tls{}, #connection_states{}}| #alert{}.
%%
%% Description: Decode cipher text
%%--------------------------------------------------------------------
@@ -496,6 +497,66 @@ decode_cipher_text(CipherText, ConnnectionStates0) ->
#alert{} = Alert ->
Alert
end.
+%%--------------------------------------------------------------------
+-spec encode_data(iolist(), tls_version(), #connection_states{}, integer()) ->
+ {iolist(), iolist(), #connection_states{}}.
+%%
+%% Description: Encodes data to send on the ssl-socket.
+%%--------------------------------------------------------------------
+encode_data(Frag, Version, ConnectionStates, RenegotiateAt)
+ when byte_size(Frag) < (?MAX_PLAIN_TEXT_LENGTH - 2048) ->
+ case encode_plain_text(?APPLICATION_DATA,Version,Frag,ConnectionStates, RenegotiateAt) of
+ {renegotiate, Data} ->
+ {[], Data, ConnectionStates};
+ {Msg, CS} ->
+ {Msg, [], CS}
+ end;
+
+encode_data(Frag, Version, ConnectionStates, RenegotiateAt) when is_binary(Frag) ->
+ Data = split_bin(Frag, ?MAX_PLAIN_TEXT_LENGTH - 2048),
+ encode_data(Data, Version, ConnectionStates, RenegotiateAt);
+
+encode_data(Data, Version, ConnectionStates0, RenegotiateAt) when is_list(Data) ->
+ {ConnectionStates, EncodedMsg, NotEncdedData} =
+ lists:foldl(fun(B, {CS0, Encoded, Rest}) ->
+ case encode_plain_text(?APPLICATION_DATA,
+ Version, B, CS0, RenegotiateAt) of
+ {renegotiate, NotEnc} ->
+ {CS0, Encoded, [NotEnc | Rest]};
+ {Enc, CS1} ->
+ {CS1, [Enc | Encoded], Rest}
+ end
+ end, {ConnectionStates0, [], []}, Data),
+ {lists:reverse(EncodedMsg), lists:reverse(NotEncdedData), ConnectionStates}.
+
+%%--------------------------------------------------------------------
+-spec encode_handshake(iolist(), tls_version(), #connection_states{}) ->
+ {iolist(), #connection_states{}}.
+%%
+%% Description: Encodes a handshake message to send on the ssl-socket.
+%%--------------------------------------------------------------------
+encode_handshake(Frag, Version, ConnectionStates) ->
+ encode_plain_text(?HANDSHAKE, Version, Frag, ConnectionStates).
+
+%%--------------------------------------------------------------------
+-spec encode_alert_record(#alert{}, tls_version(), #connection_states{}) ->
+ {iolist(), #connection_states{}}.
+%%
+%% Description: Encodes an alert message to send on the ssl-socket.
+%%--------------------------------------------------------------------
+encode_alert_record(#alert{level = Level, description = Description},
+ Version, ConnectionStates) ->
+ encode_plain_text(?ALERT, Version, <<?BYTE(Level), ?BYTE(Description)>>,
+ ConnectionStates).
+
+%%--------------------------------------------------------------------
+-spec encode_change_cipher_spec(tls_version(), #connection_states{}) ->
+ {iolist(), #connection_states{}}.
+%%
+%% Description: Encodes a change_cipher_spec-message to send on the ssl socket.
+%%--------------------------------------------------------------------
+encode_change_cipher_spec(Version, ConnectionStates) ->
+ encode_plain_text(?CHANGE_CIPHER_SPEC, Version, <<1:8>>, ConnectionStates).
%%--------------------------------------------------------------------
%%% Internal functions
@@ -549,43 +610,6 @@ split_bin(Bin, ChunkSize, Acc) ->
lists:reverse(Acc, [Bin])
end.
-encode_data(Frag, Version, ConnectionStates, RenegotiateAt)
- when byte_size(Frag) < (?MAX_PLAIN_TEXT_LENGTH - 2048) ->
- case encode_plain_text(?APPLICATION_DATA,Version,Frag,ConnectionStates, RenegotiateAt) of
- {renegotiate, Data} ->
- {[], Data, ConnectionStates};
- {Msg, CS} ->
- {Msg, [], CS}
- end;
-
-encode_data(Frag, Version, ConnectionStates, RenegotiateAt) when is_binary(Frag) ->
- Data = split_bin(Frag, ?MAX_PLAIN_TEXT_LENGTH - 2048),
- encode_data(Data, Version, ConnectionStates, RenegotiateAt);
-
-encode_data(Data, Version, ConnectionStates0, RenegotiateAt) when is_list(Data) ->
- {ConnectionStates, EncodedMsg, NotEncdedData} =
- lists:foldl(fun(B, {CS0, Encoded, Rest}) ->
- case encode_plain_text(?APPLICATION_DATA,
- Version, B, CS0, RenegotiateAt) of
- {renegotiate, NotEnc} ->
- {CS0, Encoded, [NotEnc | Rest]};
- {Enc, CS1} ->
- {CS1, [Enc | Encoded], Rest}
- end
- end, {ConnectionStates0, [], []}, Data),
- {lists:reverse(EncodedMsg), lists:reverse(NotEncdedData), ConnectionStates}.
-
-encode_handshake(Frag, Version, ConnectionStates) ->
- encode_plain_text(?HANDSHAKE, Version, Frag, ConnectionStates).
-
-encode_alert_record(#alert{level = Level, description = Description},
- Version, ConnectionStates) ->
- encode_plain_text(?ALERT, Version, <<?BYTE(Level), ?BYTE(Description)>>,
- ConnectionStates).
-
-encode_change_cipher_spec(Version, ConnectionStates) ->
- encode_plain_text(?CHANGE_CIPHER_SPEC, Version, <<1:8>>, ConnectionStates).
-
encode_plain_text(Type, Version, Data, ConnectionStates, RenegotiateAt) ->
#connection_states{current_write =
#connection_state{sequence_number = Num}} = ConnectionStates,
diff --git a/lib/ssl/src/ssl_session.erl b/lib/ssl/src/ssl_session.erl
index e9755cb0e1..25e7445180 100644
--- a/lib/ssl/src/ssl_session.erl
+++ b/lib/ssl/src/ssl_session.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -35,7 +35,7 @@
-type seconds() :: integer().
%%--------------------------------------------------------------------
--spec is_new(binary(), binary()) -> boolean().
+-spec is_new(session_id(), session_id()) -> boolean().
%%
%% Description: Checks if the session id decided by the server is a
%% new or resumed sesion id.
@@ -113,7 +113,7 @@ select_session(Sessions, #ssl_options{ciphers = Ciphers,
List ->
hd(List)
end.
-
+
%% If we can not generate a not allready in use session ID in
%% ?GEN_UNIQUE_ID_MAX_TRIES we make the new session uncacheable The
%% value of ?GEN_UNIQUE_ID_MAX_TRIES is stolen from open SSL which
diff --git a/lib/ssl/src/ssl_ssl3.erl b/lib/ssl/src/ssl_ssl3.erl
index 375adf263a..f3cb6ad66e 100644
--- a/lib/ssl/src/ssl_ssl3.erl
+++ b/lib/ssl/src/ssl_ssl3.erl
@@ -79,10 +79,9 @@ finished(Role, MasterSecret, {MD5Hash, SHAHash}) ->
SHA = handshake_hash(?SHA, MasterSecret, Sender, SHAHash),
<<MD5/binary, SHA/binary>>.
--spec certificate_verify(key_algo(), binary(), {binary(), binary()}) -> binary().
+-spec certificate_verify(OID::tuple(), binary(), {binary(), binary()}) -> binary().
-certificate_verify(Algorithm, MasterSecret, {MD5Hash, SHAHash})
- when Algorithm == rsa; Algorithm == dhe_rsa ->
+certificate_verify(?'rsaEncryption', MasterSecret, {MD5Hash, SHAHash}) ->
%% md5_hash
%% MD5(master_secret + pad_2 +
%% MD5(handshake_messages + master_secret + pad_1));
@@ -94,7 +93,7 @@ certificate_verify(Algorithm, MasterSecret, {MD5Hash, SHAHash})
SHA = handshake_hash(?SHA, MasterSecret, undefined, SHAHash),
<<MD5/binary, SHA/binary>>;
-certificate_verify(dhe_dss, MasterSecret, {_, SHAHash}) ->
+certificate_verify(?'id-dsa', MasterSecret, {_, SHAHash}) ->
%% sha_hash
%% SHA(master_secret + pad_2 +
%% SHA(handshake_messages + master_secret + pad_1));
@@ -121,9 +120,10 @@ mac_hash(Method, Mac_write_secret, Seq_num, Type, Length, Fragment) ->
?DBG_HEX(Mac),
Mac.
--spec setup_keys(binary(), binary(), binary(), binary(),
- integer(), integer(), binary()) -> {binary(), binary(), binary(),
- binary(), binary(), binary()}.
+-spec setup_keys(binary(), binary(), binary(),
+ integer(), integer(), term(), integer()) ->
+ {binary(), binary(), binary(),
+ binary(), binary(), binary()}.
setup_keys(MasterSecret, ServerRandom, ClientRandom, HS, KML, _EKML, IVS) ->
KeyBlock = generate_keyblock(MasterSecret, ServerRandom, ClientRandom,
diff --git a/lib/ssl/src/ssl_sup.erl b/lib/ssl/src/ssl_sup.erl
index b7cb5c3ab3..316ed8a4e9 100644
--- a/lib/ssl/src/ssl_sup.erl
+++ b/lib/ssl/src/ssl_sup.erl
@@ -32,14 +32,17 @@
%%%=========================================================================
%%% API
%%%=========================================================================
+
+-spec start_link() -> {ok, pid()} | ignore | {error, term()}.
+
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
-%% init([]) -> {ok, {SupFlags, [ChildSpec]}}
-%%
+-spec init([]) -> {ok, {SupFlags :: tuple(), [ChildSpec :: tuple()]}}.
+
init([]) ->
%% OLD ssl - moved start to ssl.erl only if old
%% ssl is acctualy run!
diff --git a/lib/ssl/src/ssl_tls1.erl b/lib/ssl/src/ssl_tls1.erl
index d1bc0730ba..dd66418dd8 100644
--- a/lib/ssl/src/ssl_tls1.erl
+++ b/lib/ssl/src/ssl_tls1.erl
@@ -60,15 +60,14 @@ finished(Role, MasterSecret, {MD5Hash, SHAHash}) ->
SHA = hash_final(?SHA, SHAHash),
prf(MasterSecret, finished_label(Role), [MD5, SHA], 12).
--spec certificate_verify(key_algo(), {binary(), binary()}) -> binary().
+-spec certificate_verify(OID::tuple(), {binary(), binary()}) -> binary().
-certificate_verify(Algorithm, {MD5Hash, SHAHash}) when Algorithm == rsa;
- Algorithm == dhe_rsa ->
+certificate_verify(?'rsaEncryption', {MD5Hash, SHAHash}) ->
MD5 = hash_final(?MD5, MD5Hash),
SHA = hash_final(?SHA, SHAHash),
<<MD5/binary, SHA/binary>>;
-certificate_verify(dhe_dss, {_, SHAHash}) ->
+certificate_verify(?'id-dsa', {_, SHAHash}) ->
hash_final(?SHA, SHAHash).
-spec setup_keys(binary(), binary(), binary(), integer(),
diff --git a/lib/ssl/test/Makefile b/lib/ssl/test/Makefile
index 9e4aecac45..c0a7f8d257 100644
--- a/lib/ssl/test/Makefile
+++ b/lib/ssl/test/Makefile
@@ -40,6 +40,7 @@ MODULES = \
ssl_packet_SUITE \
ssl_payload_SUITE \
ssl_to_openssl_SUITE \
+ ssl_session_cache_SUITE \
ssl_test_MACHINE \
old_ssl_active_SUITE \
old_ssl_active_once_SUITE \
diff --git a/lib/ssl/test/erl_make_certs.erl b/lib/ssl/test/erl_make_certs.erl
index 1d2cea6c72..8b01ca3ad4 100644
--- a/lib/ssl/test/erl_make_certs.erl
+++ b/lib/ssl/test/erl_make_certs.erl
@@ -56,7 +56,7 @@
make_cert(Opts) ->
SubjectPrivateKey = get_key(Opts),
{TBSCert, IssuerKey} = make_tbs(SubjectPrivateKey, Opts),
- Cert = public_key:sign(TBSCert, IssuerKey),
+ Cert = public_key:pkix_sign(TBSCert, IssuerKey),
true = verify_signature(Cert, IssuerKey, undef), %% verify that the keys where ok
{Cert, encode_key(SubjectPrivateKey)}.
@@ -66,8 +66,9 @@ make_cert(Opts) ->
%% @end
%%--------------------------------------------------------------------
write_pem(Dir, FileName, {Cert, Key = {_,_,not_encrypted}}) when is_binary(Cert) ->
- ok = public_key:der_to_pem(filename:join(Dir, FileName ++ ".pem"), [{cert, Cert, not_encrypted}]),
- ok = public_key:der_to_pem(filename:join(Dir, FileName ++ "_key.pem"), [Key]).
+ ok = der_to_pem(filename:join(Dir, FileName ++ ".pem"),
+ [{'Certificate', Cert, not_encrypted}]),
+ ok = der_to_pem(filename:join(Dir, FileName ++ "_key.pem"), [Key]).
%%--------------------------------------------------------------------
%% @doc Creates a rsa key (OBS: for testing only)
@@ -94,18 +95,14 @@ gen_dsa(LSize,NSize) when is_integer(LSize), is_integer(NSize) ->
%% @spec (::binary(), ::tuple()) -> ::boolean()
%% @end
%%--------------------------------------------------------------------
-verify_signature(DerEncodedCert, DerKey, KeyParams) ->
+verify_signature(DerEncodedCert, DerKey, _KeyParams) ->
Key = decode_key(DerKey),
case Key of
#'RSAPrivateKey'{modulus=Mod, publicExponent=Exp} ->
- public_key:verify_signature(DerEncodedCert,
- #'RSAPublicKey'{modulus=Mod, publicExponent=Exp},
- 'NULL');
+ public_key:pkix_verify(DerEncodedCert,
+ #'RSAPublicKey'{modulus=Mod, publicExponent=Exp});
#'DSAPrivateKey'{p=P, q=Q, g=G, y=Y} ->
- public_key:verify_signature(DerEncodedCert, Y, #'Dss-Parms'{p=P, q=Q, g=G});
-
- _ ->
- public_key:verify_signature(DerEncodedCert, Key, KeyParams)
+ public_key:pkix_verify(DerEncodedCert, {Y, #'Dss-Parms'{p=P, q=Q, g=G}})
end.
%%%%%%%%%%%%%%%%%%%%%%%%% Implementation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -132,59 +129,63 @@ decode_key(#'RSAPrivateKey'{} = Key,_) ->
Key;
decode_key(#'DSAPrivateKey'{} = Key,_) ->
Key;
-decode_key(Der = {_,_,_}, Pw) ->
- {ok, Key} = public_key:decode_private_key(Der, Pw),
- Key;
-decode_key(FileOrDer, Pw) ->
- {ok, [KeyInfo]} = public_key:pem_to_der(FileOrDer),
+decode_key(PemEntry = {_,_,_}, Pw) ->
+ public_key:pem_entry_decode(PemEntry, Pw);
+decode_key(PemBin, Pw) ->
+ [KeyInfo] = public_key:pem_decode(PemBin),
decode_key(KeyInfo, Pw).
encode_key(Key = #'RSAPrivateKey'{}) ->
{ok, Der} = 'OTP-PUB-KEY':encode('RSAPrivateKey', Key),
- {rsa_private_key, list_to_binary(Der), not_encrypted};
+ {'RSAPrivateKey', list_to_binary(Der), not_encrypted};
encode_key(Key = #'DSAPrivateKey'{}) ->
{ok, Der} = 'OTP-PUB-KEY':encode('DSAPrivateKey', Key),
- {dsa_private_key, list_to_binary(Der), not_encrypted}.
+ {'DSAPrivateKey', list_to_binary(Der), not_encrypted}.
make_tbs(SubjectKey, Opts) ->
Version = list_to_atom("v"++integer_to_list(proplists:get_value(version, Opts, 3))),
- {Issuer, IssuerKey} = issuer(Opts, SubjectKey),
+
+ IssuerProp = proplists:get_value(issuer, Opts, true),
+ {Issuer, IssuerKey} = issuer(IssuerProp, Opts, SubjectKey),
{Algo, Parameters} = sign_algorithm(IssuerKey, Opts),
SignAlgo = #'SignatureAlgorithm'{algorithm = Algo,
parameters = Parameters},
-
+ Subject = case IssuerProp of
+ true -> %% Is a Root Ca
+ Issuer;
+ _ ->
+ subject(proplists:get_value(subject, Opts),false)
+ end,
+
{#'OTPTBSCertificate'{serialNumber = trunc(random:uniform()*100000000)*10000 + 1,
signature = SignAlgo,
issuer = Issuer,
validity = validity(Opts),
- subject = subject(proplists:get_value(subject, Opts),false),
+ subject = Subject,
subjectPublicKeyInfo = publickey(SubjectKey),
version = Version,
extensions = extensions(Opts)
}, IssuerKey}.
-issuer(Opts, SubjectKey) ->
- IssuerProp = proplists:get_value(issuer, Opts, true),
- case IssuerProp of
- true -> %% Self signed
- {subject(proplists:get_value(subject, Opts), true), SubjectKey};
- {Issuer, IssuerKey} when is_binary(Issuer) ->
- {issuer_der(Issuer), decode_key(IssuerKey)};
- {File, IssuerKey} when is_list(File) ->
- {ok, [{cert, Cert, _}|_]} = public_key:pem_to_der(File),
- {issuer_der(Cert), decode_key(IssuerKey)}
- end.
+issuer(true, Opts, SubjectKey) ->
+ %% Self signed
+ {subject(proplists:get_value(subject, Opts), true), SubjectKey};
+issuer({Issuer, IssuerKey}, _Opts, _SubjectKey) when is_binary(Issuer) ->
+ {issuer_der(Issuer), decode_key(IssuerKey)};
+issuer({File, IssuerKey}, _Opts, _SubjectKey) when is_list(File) ->
+ {ok, [{cert, Cert, _}|_]} = public_key:pem_to_der(File),
+ {issuer_der(Cert), decode_key(IssuerKey)}.
issuer_der(Issuer) ->
- {ok, Decoded} = public_key:pkix_decode_cert(Issuer, otp),
+ Decoded = public_key:pkix_decode_cert(Issuer, otp),
#'OTPCertificate'{tbsCertificate=Tbs} = Decoded,
#'OTPTBSCertificate'{subject=Subject} = Tbs,
Subject.
-subject(undefined, IsCA) ->
- User = if IsCA -> "CA"; true -> os:getenv("USER") end,
+subject(undefined, IsRootCA) ->
+ User = if IsRootCA -> "RootCA"; true -> os:getenv("USER") end,
Opts = [{email, User ++ "@erlang.org"},
{name, User},
{city, "Stockholm"},
@@ -267,11 +268,11 @@ publickey(#'RSAPrivateKey'{modulus=N, publicExponent=E}) ->
subjectPublicKey = Public};
publickey(#'DSAPrivateKey'{p=P, q=Q, g=G, y=Y}) ->
Algo = #'PublicKeyAlgorithm'{algorithm= ?'id-dsa',
- parameters=#'Dss-Parms'{p=P, q=Q, g=G}},
+ parameters={params, #'Dss-Parms'{p=P, q=Q, g=G}}},
#'OTPSubjectPublicKeyInfo'{algorithm = Algo, subjectPublicKey = Y}.
validity(Opts) ->
- DefFrom0 = date(),
+ DefFrom0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())-1),
DefTo0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())+7),
{DefFrom, DefTo} = proplists:get_value(validity, Opts, {DefFrom0, DefTo0}),
Format = fun({Y,M,D}) -> lists:flatten(io_lib:format("~w~2..0w~2..0w000000Z",[Y,M,D])) end,
@@ -289,7 +290,7 @@ sign_algorithm(#'RSAPrivateKey'{}, Opts) ->
end,
{Type, 'NULL'};
sign_algorithm(#'DSAPrivateKey'{p=P, q=Q, g=G}, _Opts) ->
- {?'id-dsa-with-sha1', #'Dss-Parms'{p=P, q=Q, g=G}}.
+ {?'id-dsa-with-sha1', {params,#'Dss-Parms'{p=P, q=Q, g=G}}}.
make_key(rsa, _Opts) ->
%% (OBS: for testing only)
@@ -410,3 +411,11 @@ extended_gcd(A, B) ->
{X, Y} = extended_gcd(B, N),
{Y, X-Y*(A div B)}
end.
+
+pem_to_der(File) ->
+ {ok, PemBin} = file:read_file(File),
+ public_key:pem_decode(PemBin).
+
+der_to_pem(File, Entries) ->
+ PemBin = public_key:pem_encode(Entries),
+ file:write_file(File, PemBin).
diff --git a/lib/ssl/test/make_certs.erl b/lib/ssl/test/make_certs.erl
index 0cdf33c3e2..3c18a905b4 100644
--- a/lib/ssl/test/make_certs.erl
+++ b/lib/ssl/test/make_certs.erl
@@ -90,8 +90,10 @@ enduser(Root, OpenSSLCmd, CA, User) ->
KeyFile = filename:join([UsrRoot, "key.pem"]),
ReqFile = filename:join([UsrRoot, "req.pem"]),
create_req(Root, OpenSSLCmd, CnfFile, KeyFile, ReqFile),
- CertFile = filename:join([UsrRoot, "cert.pem"]),
- sign_req(Root, OpenSSLCmd, CA, "user_cert", ReqFile, CertFile).
+ CertFileAllUsage = filename:join([UsrRoot, "cert.pem"]),
+ sign_req(Root, OpenSSLCmd, CA, "user_cert", ReqFile, CertFileAllUsage),
+ CertFileDigitalSigOnly = filename:join([UsrRoot, "digital_signature_only_cert.pem"]),
+ sign_req(Root, OpenSSLCmd, CA, "user_cert_digital_signature_only", ReqFile, CertFileDigitalSigOnly).
collect_certs(Root, CAs, Users) ->
Bins = lists:foldr(
@@ -255,6 +257,7 @@ ca_cnf(CA) ->
"RANDFILE = $dir/private/RAND\n"
"\n"
"x509_extensions = user_cert\n"
+ "unique_subject = no\n"
"default_days = 3600\n"
"default_md = sha1\n"
"preserve = no\n"
@@ -279,6 +282,15 @@ ca_cnf(CA) ->
"issuerAltName = issuer:copy\n"
"\n"
+ "[user_cert_digital_signature_only]\n"
+ "basicConstraints = CA:false\n"
+ "keyUsage = digitalSignature\n"
+ "subjectKeyIdentifier = hash\n"
+ "authorityKeyIdentifier = keyid,issuer:always\n"
+ "subjectAltName = email:copy\n"
+ "issuerAltName = issuer:copy\n"
+ "\n"
+
"[ca_cert]\n"
"basicConstraints = critical,CA:true\n"
"keyUsage = cRLSign, keyCertSign\n"
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index 8a1b90ed98..ea84b3c9d1 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -7,7 +7,7 @@
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
+%% retrieved online at http://www.erlang.org/.2
%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
@@ -34,12 +34,6 @@
-define(EXPIRE, 10).
-define(SLEEP, 500).
--behaviour(ssl_session_cache_api).
-
-%% For the session cache tests
--export([init/1, terminate/1, lookup/2, update/3,
- delete/2, foldl/3, select_session/2]).
-
%% Test server callback functions
%%--------------------------------------------------------------------
%% Function: init_per_suite(Config) -> Config
@@ -89,13 +83,6 @@ end_per_suite(_Config) ->
%% variable, but should NOT alter/remove any existing entries.
%% Description: Initialization before each test case
%%--------------------------------------------------------------------
-init_per_testcase(session_cache_process_list, Config) ->
- init_customized_session_cache(list, Config);
-
-init_per_testcase(session_cache_process_mnesia, Config) ->
- mnesia:start(),
- init_customized_session_cache(mnesia, Config);
-
init_per_testcase(reuse_session_expired, Config0) ->
Config = lists:keydelete(watchdog, 1, Config0),
Dog = ssl_test_lib:timetrap(?EXPIRE * 1000 * 5),
@@ -142,16 +129,6 @@ init_per_testcase(_TestCase, Config0) ->
Dog = test_server:timetrap(?TIMEOUT),
[{watchdog, Dog} | Config].
-init_customized_session_cache(Type, Config0) ->
- Config = lists:keydelete(watchdog, 1, Config0),
- Dog = test_server:timetrap(?TIMEOUT),
- ssl:stop(),
- application:load(ssl),
- application:set_env(ssl, session_cb, ?MODULE),
- application:set_env(ssl, session_cb_init_args, [Type]),
- ssl:start(),
- [{watchdog, Dog} | Config].
-
%%--------------------------------------------------------------------
%% Function: end_per_testcase(TestCase, Config) -> _
%% Case - atom()
@@ -160,16 +137,6 @@ init_customized_session_cache(Type, Config0) ->
%% A list of key/value pairs, holding the test case configuration.
%% Description: Cleanup after each test case
%%--------------------------------------------------------------------
-end_per_testcase(session_cache_process_list, Config) ->
- application:unset_env(ssl, session_cb),
- end_per_testcase(default_action, Config);
-end_per_testcase(session_cache_process_mnesia, Config) ->
- application:unset_env(ssl, session_cb),
- application:unset_env(ssl, session_cb_init_args),
- mnesia:stop(),
- ssl:stop(),
- ssl:start(),
- end_per_testcase(default_action, Config);
end_per_testcase(reuse_session_expired, Config) ->
application:unset_env(ssl, session_lifetime),
end_per_testcase(default_action, Config);
@@ -216,6 +183,8 @@ all(suite) ->
ciphers_dsa_signed_certs_ssl3,
ciphers_dsa_signed_certs_openssl_names,
ciphers_dsa_signed_certs_openssl_names_ssl3,
+ anonymous_cipher_suites,
+ default_reject_anonymous,
send_close,
close_transport_accept, dh_params, server_verify_peer_passive,
server_verify_peer_active, server_verify_peer_active_once,
@@ -226,14 +195,16 @@ all(suite) ->
server_verify_client_once_active,
server_verify_client_once_active_once, client_verify_none_passive,
client_verify_none_active, client_verify_none_active_once,
- session_cache_process_list, session_cache_process_mnesia,
reuse_session, reuse_session_expired,
server_does_not_want_to_reuse_session, client_renegotiate,
server_renegotiate, client_renegotiate_reused_session,
server_renegotiate_reused_session, client_no_wrap_sequence_number,
server_no_wrap_sequence_number, extended_key_usage,
- validate_extensions_fun, no_authority_key_identifier,
- invalid_signature_client, invalid_signature_server, cert_expired
+ no_authority_key_identifier,
+ invalid_signature_client, invalid_signature_server, cert_expired,
+ client_with_cert_cipher_suites_handshake, unknown_server_ca_fail,
+ der_input, unknown_server_ca_accept_verify_none, unknown_server_ca_accept_verify_peer,
+ unknown_server_ca_accept_backwardscompatibilty
].
%% Test cases starts here.
@@ -578,8 +549,8 @@ peercert(Config) when is_list(Config) ->
{options, ClientOpts}]),
CertFile = proplists:get_value(certfile, ServerOpts),
- {ok, [{cert, BinCert, _}]} = public_key:pem_to_der(CertFile),
- {ok, ErlCert} = public_key:pkix_decode_cert(BinCert, otp),
+ [{'Certificate', BinCert, _}]= ssl_test_lib:pem_to_der(CertFile),
+ ErlCert = public_key:pkix_decode_cert(BinCert, otp),
ServerMsg = {{error, no_peercert}, {error, no_peercert}},
ClientMsg = {{ok, BinCert}, {ok, ErlCert}},
@@ -1162,13 +1133,13 @@ ecertfile(Config) when is_list(Config) ->
Server =
ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
{from, self()},
- {options, ServerBadOpts}]),
+ {options, ServerBadOpts}]),
Port = ssl_test_lib:inet_port(Server),
Client =
ssl_test_lib:start_client_error([{node, ClientNode},
- {port, Port}, {host, Hostname},
+ {port, Port}, {host, Hostname},
{from, self()},
{options, ClientOpts}]),
@@ -1258,7 +1229,6 @@ eoptions(Config) when is_list(Config) ->
{verify_fun, function},
{fail_if_no_peer_cert, 0},
{verify_client_once, 1},
- {validate_extensions_fun, function},
{depth, four},
{certfile, 'cert.pem'},
{keyfile,'key.pem' },
@@ -1520,6 +1490,14 @@ ciphers_dsa_signed_certs_openssl_names_ssl3(Config) when is_list(Config) ->
Ciphers = ssl_test_lib:openssl_dsa_suites(),
run_suites(Ciphers, Version, Config, dsa).
+anonymous_cipher_suites(doc)->
+ ["Test the anonymous ciphersuites"];
+anonymous_cipher_suites(suite) ->
+ [];
+anonymous_cipher_suites(Config) when is_list(Config) ->
+ Version = ssl_record:protocol_version(ssl_record:highest_protocol_version([])),
+ Ciphers = ssl_test_lib:anonymous_suites(),
+ run_suites(Ciphers, Version, Config, anonymous).
run_suites(Ciphers, Version, Config, Type) ->
{ClientOpts, ServerOpts} =
@@ -1529,8 +1507,12 @@ run_suites(Ciphers, Version, Config, Type) ->
?config(server_opts, Config)};
dsa ->
{?config(client_opts, Config),
- ?config(server_dsa_opts, Config)}
- end,
+ ?config(server_dsa_opts, Config)};
+ anonymous ->
+ %% No certs in opts!
+ {?config(client_opts, Config),
+ ?config(server_anon, Config)}
+ end,
Result = lists:map(fun(Cipher) ->
cipher(Cipher, Version, Config, ClientOpts, ServerOpts) end,
@@ -1552,25 +1534,26 @@ cipher(CipherSuite, Version, Config, ClientOpts, ServerOpts) ->
process_flag(trap_exit, true),
test_server:format("Testing CipherSuite ~p~n", [CipherSuite]),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ ErlangCipherSuite = erlang_cipher_suite(CipherSuite),
+
+ ConnectionInfo = {ok, {Version, ErlangCipherSuite}},
+
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
- {mfa, {?MODULE, connection_info_result, []}},
+ {mfa, {ssl_test_lib, cipher_result, [ConnectionInfo]}},
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
- {mfa, {?MODULE, connection_info_result, []}},
+ {mfa, {ssl_test_lib, cipher_result, [ConnectionInfo]}},
{options,
[{ciphers,[CipherSuite]} |
ClientOpts]}]),
-
- ErlangCipherSuite = erlang_cipher_suite(CipherSuite),
-
- ServerMsg = ClientMsg = {ok, {Version, ErlangCipherSuite}},
-
- Result = ssl_test_lib:wait_for_result(Server, ServerMsg,
- Client, ClientMsg),
+
+ Result = ssl_test_lib:wait_for_result(Server, ok, Client, ok),
+
ssl_test_lib:close(Server),
receive
{'EXIT', Server, normal} ->
@@ -1590,6 +1573,32 @@ cipher(CipherSuite, Version, Config, ClientOpts, ServerOpts) ->
end.
%%--------------------------------------------------------------------
+default_reject_anonymous(doc)->
+ ["Test that by default anonymous cipher suites are rejected "];
+default_reject_anonymous(suite) ->
+ [];
+default_reject_anonymous(Config) when is_list(Config) ->
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+
+ [Cipher | _] = ssl_test_lib:anonymous_suites(),
+
+ Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {options,
+ [{ciphers,[Cipher]} |
+ ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, {error, "insufficient security"},
+ Client, {error, "insufficient security"}).
+
+%%--------------------------------------------------------------------
reuse_session(doc) ->
["Test reuse of sessions (short handshake)"];
@@ -2268,14 +2277,7 @@ client_verify_none_active_once(Config) when is_list(Config) ->
{mfa, {?MODULE, send_recv_result_active_once, []}},
{options, [{active, once} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
- %% TODO: send message to test process to make sure
- %% verifyfun has beeen run as it has the same behavior as
- %% the default fun
- VerifyFun = fun([{bad_cert, unknown_ca}]) ->
- true;
- (_) ->
- false
- end,
+
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
@@ -2283,8 +2285,7 @@ client_verify_none_active_once(Config) when is_list(Config) ->
send_recv_result_active_once,
[]}},
{options, [{active, once},
- {verify, verify_none},
- {verify_fun, VerifyFun}
+ {verify, verify_none}
| ClientOpts]}]),
ssl_test_lib:check_result(Server, ok, Client, ok),
@@ -2525,35 +2526,35 @@ extended_key_usage(Config) when is_list(Config) ->
PrivDir = ?config(priv_dir, Config),
KeyFile = filename:join(PrivDir, "otpCA/private/key.pem"),
- {ok, [KeyInfo]} = public_key:pem_to_der(KeyFile),
- {ok, Key} = public_key:decode_private_key(KeyInfo),
+ [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile),
+ Key = public_key:pem_entry_decode(KeyEntry),
ServerCertFile = proplists:get_value(certfile, ServerOpts),
NewServerCertFile = filename:join(PrivDir, "server/new_cert.pem"),
- {ok, [{cert, ServerDerCert, _}]} = public_key:pem_to_der(ServerCertFile),
- {ok, ServerOTPCert} = public_key:pkix_decode_cert(ServerDerCert, otp),
+ [{'Certificate', ServerDerCert, _}] = ssl_test_lib:pem_to_der(ServerCertFile),
+ ServerOTPCert = public_key:pkix_decode_cert(ServerDerCert, otp),
ServerExtKeyUsageExt = {'Extension', ?'id-ce-extKeyUsage', true, [?'id-kp-serverAuth']},
ServerOTPTbsCert = ServerOTPCert#'OTPCertificate'.tbsCertificate,
ServerExtensions = ServerOTPTbsCert#'OTPTBSCertificate'.extensions,
NewServerOTPTbsCert = ServerOTPTbsCert#'OTPTBSCertificate'{extensions =
[ServerExtKeyUsageExt |
ServerExtensions]},
- NewServerDerCert = public_key:sign(NewServerOTPTbsCert, Key),
- public_key:der_to_pem(NewServerCertFile, [{cert, NewServerDerCert, not_encrypted}]),
+ NewServerDerCert = public_key:pkix_sign(NewServerOTPTbsCert, Key),
+ ssl_test_lib:der_to_pem(NewServerCertFile, [{'Certificate', NewServerDerCert, not_encrypted}]),
NewServerOpts = [{certfile, NewServerCertFile} | proplists:delete(certfile, ServerOpts)],
ClientCertFile = proplists:get_value(certfile, ClientOpts),
NewClientCertFile = filename:join(PrivDir, "client/new_cert.pem"),
- {ok, [{cert, ClientDerCert, _}]} = public_key:pem_to_der(ClientCertFile),
- {ok, ClientOTPCert} = public_key:pkix_decode_cert(ClientDerCert, otp),
+ [{'Certificate', ClientDerCert, _}] = ssl_test_lib:pem_to_der(ClientCertFile),
+ ClientOTPCert = public_key:pkix_decode_cert(ClientDerCert, otp),
ClientExtKeyUsageExt = {'Extension', ?'id-ce-extKeyUsage', true, [?'id-kp-clientAuth']},
ClientOTPTbsCert = ClientOTPCert#'OTPCertificate'.tbsCertificate,
ClientExtensions = ClientOTPTbsCert#'OTPTBSCertificate'.extensions,
NewClientOTPTbsCert = ClientOTPTbsCert#'OTPTBSCertificate'{extensions =
[ClientExtKeyUsageExt |
ClientExtensions]},
- NewClientDerCert = public_key:sign(NewClientOTPTbsCert, Key),
- public_key:der_to_pem(NewClientCertFile, [{cert, NewClientDerCert, not_encrypted}]),
+ NewClientDerCert = public_key:pkix_sign(NewClientOTPTbsCert, Key),
+ ssl_test_lib:der_to_pem(NewClientCertFile, [{'Certificate', NewClientDerCert, not_encrypted}]),
NewClientOpts = [{certfile, NewClientCertFile} | proplists:delete(certfile, ClientOpts)],
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
@@ -2575,59 +2576,25 @@ extended_key_usage(Config) when is_list(Config) ->
ssl_test_lib:close(Client).
%%--------------------------------------------------------------------
-validate_extensions_fun(doc) ->
- ["Test that it is possible to specify a validate_extensions_fun"];
-
-validate_extensions_fun(suite) ->
- [];
-
-validate_extensions_fun(Config) when is_list(Config) ->
- ClientOpts = ?config(client_verification_opts, Config),
- ServerOpts = ?config(server_verification_opts, Config),
-
- Fun = fun(Extensions, State, _, AccError) ->
- {Extensions, State, AccError}
- end,
-
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {?MODULE, send_recv_result_active, []}},
- {options, [{validate_extensions_fun, Fun},
- {verify, verify_peer} | ServerOpts]}]),
- Port = ssl_test_lib:inet_port(Server),
-
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE, send_recv_result_active, []}},
- {options,[{validate_extensions_fun, Fun} | ClientOpts]}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
no_authority_key_identifier(doc) ->
- ["Test cert that does not have authorityKeyIdentifier extension"];
+ ["Test cert that does not have authorityKeyIdentifier extension"
+ " but are present in trusted certs db."];
no_authority_key_identifier(suite) ->
[];
no_authority_key_identifier(Config) when is_list(Config) ->
- ClientOpts = ?config(client_opts, Config),
+ ClientOpts = ?config(client_verification_opts, Config),
ServerOpts = ?config(server_opts, Config),
PrivDir = ?config(priv_dir, Config),
KeyFile = filename:join(PrivDir, "otpCA/private/key.pem"),
- {ok, [KeyInfo]} = public_key:pem_to_der(KeyFile),
- {ok, Key} = public_key:decode_private_key(KeyInfo),
+ [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile),
+ Key = public_key:pem_entry_decode(KeyEntry),
CertFile = proplists:get_value(certfile, ServerOpts),
NewCertFile = filename:join(PrivDir, "server/new_cert.pem"),
- {ok, [{cert, DerCert, _}]} = public_key:pem_to_der(CertFile),
- {ok, OTPCert} = public_key:pkix_decode_cert(DerCert, otp),
+ [{'Certificate', DerCert, _}] = ssl_test_lib:pem_to_der(CertFile),
+ OTPCert = public_key:pkix_decode_cert(DerCert, otp),
OTPTbsCert = OTPCert#'OTPCertificate'.tbsCertificate,
Extensions = OTPTbsCert#'OTPTBSCertificate'.extensions,
NewExtensions = delete_authority_key_extension(Extensions, []),
@@ -2635,8 +2602,8 @@ no_authority_key_identifier(Config) when is_list(Config) ->
test_server:format("Extensions ~p~n, NewExtensions: ~p~n", [Extensions, NewExtensions]),
- NewDerCert = public_key:sign(NewOTPTbsCert, Key),
- public_key:der_to_pem(NewCertFile, [{cert, NewDerCert, not_encrypted}]),
+ NewDerCert = public_key:pkix_sign(NewOTPTbsCert, Key),
+ ssl_test_lib:der_to_pem(NewCertFile, [{'Certificate', NewDerCert, not_encrypted}]),
NewServerOpts = [{certfile, NewCertFile} | proplists:delete(certfile, ServerOpts)],
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
@@ -2674,21 +2641,21 @@ invalid_signature_server(suite) ->
[];
invalid_signature_server(Config) when is_list(Config) ->
- ClientOpts = ?config(client_opts, Config),
+ ClientOpts = ?config(client_verification_opts, Config),
ServerOpts = ?config(server_verification_opts, Config),
PrivDir = ?config(priv_dir, Config),
KeyFile = filename:join(PrivDir, "server/key.pem"),
- {ok, [KeyInfo]} = public_key:pem_to_der(KeyFile),
- {ok, Key} = public_key:decode_private_key(KeyInfo),
+ [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile),
+ Key = public_key:pem_entry_decode(KeyEntry),
ServerCertFile = proplists:get_value(certfile, ServerOpts),
NewServerCertFile = filename:join(PrivDir, "server/invalid_cert.pem"),
- {ok, [{cert, ServerDerCert, _}]} = public_key:pem_to_der(ServerCertFile),
- {ok, ServerOTPCert} = public_key:pkix_decode_cert(ServerDerCert, otp),
+ [{'Certificate', ServerDerCert, _}] = ssl_test_lib:pem_to_der(ServerCertFile),
+ ServerOTPCert = public_key:pkix_decode_cert(ServerDerCert, otp),
ServerOTPTbsCert = ServerOTPCert#'OTPCertificate'.tbsCertificate,
- NewServerDerCert = public_key:sign(ServerOTPTbsCert, Key),
- public_key:der_to_pem(NewServerCertFile, [{cert, NewServerDerCert, not_encrypted}]),
+ NewServerDerCert = public_key:pkix_sign(ServerOTPTbsCert, Key),
+ ssl_test_lib:der_to_pem(NewServerCertFile, [{'Certificate', NewServerDerCert, not_encrypted}]),
NewServerOpts = [{certfile, NewServerCertFile} | proplists:delete(certfile, ServerOpts)],
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
@@ -2719,16 +2686,16 @@ invalid_signature_client(Config) when is_list(Config) ->
PrivDir = ?config(priv_dir, Config),
KeyFile = filename:join(PrivDir, "client/key.pem"),
- {ok, [KeyInfo]} = public_key:pem_to_der(KeyFile),
- {ok, Key} = public_key:decode_private_key(KeyInfo),
+ [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile),
+ Key = public_key:pem_entry_decode(KeyEntry),
ClientCertFile = proplists:get_value(certfile, ClientOpts),
NewClientCertFile = filename:join(PrivDir, "client/invalid_cert.pem"),
- {ok, [{cert, ClientDerCert, _}]} = public_key:pem_to_der(ClientCertFile),
- {ok, ClientOTPCert} = public_key:pkix_decode_cert(ClientDerCert, otp),
+ [{'Certificate', ClientDerCert, _}] = ssl_test_lib:pem_to_der(ClientCertFile),
+ ClientOTPCert = public_key:pkix_decode_cert(ClientDerCert, otp),
ClientOTPTbsCert = ClientOTPCert#'OTPCertificate'.tbsCertificate,
- NewClientDerCert = public_key:sign(ClientOTPTbsCert, Key),
- public_key:der_to_pem(NewClientCertFile, [{cert, NewClientDerCert, not_encrypted}]),
+ NewClientDerCert = public_key:pkix_sign(ClientOTPTbsCert, Key),
+ ssl_test_lib:der_to_pem(NewClientCertFile, [{'Certificate', NewClientDerCert, not_encrypted}]),
NewClientOpts = [{certfile, NewClientCertFile} | proplists:delete(certfile, ClientOpts)],
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
@@ -2745,7 +2712,7 @@ invalid_signature_client(Config) when is_list(Config) ->
tcp_delivery_workaround(Server, {error, "bad certificate"},
Client, {error,"bad certificate"}).
-tcp_delivery_workaround(Server, ServMsg, Client, ClientMsg) ->
+tcp_delivery_workaround(Server, ServerMsg, Client, ClientMsg) ->
receive
{Server, ServerMsg} ->
receive
@@ -2791,18 +2758,18 @@ cert_expired(suite) ->
[];
cert_expired(Config) when is_list(Config) ->
- ClientOpts = ?config(client_opts, Config),
+ ClientOpts = ?config(client_verification_opts, Config),
ServerOpts = ?config(server_verification_opts, Config),
PrivDir = ?config(priv_dir, Config),
KeyFile = filename:join(PrivDir, "otpCA/private/key.pem"),
- {ok, [KeyInfo]} = public_key:pem_to_der(KeyFile),
- {ok, Key} = public_key:decode_private_key(KeyInfo),
+ [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile),
+ Key = public_key:pem_entry_decode(KeyEntry),
ServerCertFile = proplists:get_value(certfile, ServerOpts),
NewServerCertFile = filename:join(PrivDir, "server/expired_cert.pem"),
- {ok, [{cert, DerCert, _}]} = public_key:pem_to_der(ServerCertFile),
- {ok, OTPCert} = public_key:pkix_decode_cert(DerCert, otp),
+ [{'Certificate', DerCert, _}] = ssl_test_lib:pem_to_der(ServerCertFile),
+ OTPCert = public_key:pkix_decode_cert(DerCert, otp),
OTPTbsCert = OTPCert#'OTPCertificate'.tbsCertificate,
{Year, Month, Day} = date(),
@@ -2825,8 +2792,8 @@ cert_expired(Config) when is_list(Config) ->
[OTPTbsCert#'OTPTBSCertificate'.validity, NewValidity]),
NewOTPTbsCert = OTPTbsCert#'OTPTBSCertificate'{validity = NewValidity},
- NewServerDerCert = public_key:sign(NewOTPTbsCert, Key),
- public_key:der_to_pem(NewServerCertFile, [{cert, NewServerDerCert, not_encrypted}]),
+ NewServerDerCert = public_key:pkix_sign(NewOTPTbsCert, Key),
+ ssl_test_lib:der_to_pem(NewServerCertFile, [{'Certificate', NewServerDerCert, not_encrypted}]),
NewServerOpts = [{certfile, NewServerCertFile} | proplists:delete(certfile, ServerOpts)],
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
@@ -2849,8 +2816,254 @@ two_digits_str(N) ->
lists:flatten(io_lib:format("~p", [N])).
%%--------------------------------------------------------------------
+
+client_with_cert_cipher_suites_handshake(doc) ->
+ ["Test that client with a certificate without keyEncipherment usage "
+ " extension can connect to a server with restricted cipher suites "];
+
+client_with_cert_cipher_suites_handshake(suite) ->
+ [];
+
+client_with_cert_cipher_suites_handshake(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_verification_opts_digital_signature_only, Config),
+ ServerOpts = ?config(server_verification_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE,
+ send_recv_result_active, []}},
+ {options, [{active, true},
+ {ciphers, ssl_test_lib:rsa_non_signed_suites()}
+ | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE,
+ send_recv_result_active, []}},
+ {options, [{active, true}
+ | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+%%--------------------------------------------------------------------
+unknown_server_ca_fail(doc) ->
+ ["Test that the client fails if the ca is unknown in verify_peer mode"];
+unknown_server_ca_fail(suite) ->
+ [];
+unknown_server_ca_fail(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ no_result, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ FunAndState = {fun(_,{bad_cert, unknown_ca} = Reason, _) ->
+ {fail, Reason};
+ (_,{extension, _}, UserState) ->
+ {unknown, UserState};
+ (_, valid, UserState) ->
+ {valid, [test_to_update_user_state | UserState]};
+ (_, valid_peer, UserState) ->
+ {valid, UserState}
+ end, []},
+
+ Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ no_result, []}},
+ {options,
+ [{verify, verify_peer},
+ {verify_fun, FunAndState}
+ | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, {error,"unknown ca"},
+ Client, {error, "unknown ca"}),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+unknown_server_ca_accept_verify_none(doc) ->
+ ["Test that the client succeds if the ca is unknown in verify_none mode"];
+unknown_server_ca_accept_verify_none(suite) ->
+ [];
+unknown_server_ca_accept_verify_none(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE,
+ send_recv_result_active, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE,
+ send_recv_result_active, []}},
+ {options,
+ [{verify, verify_none}| ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+%%--------------------------------------------------------------------
+unknown_server_ca_accept_verify_peer(doc) ->
+ ["Test that the client succeds if the ca is unknown in verify_peer mode"
+ " with a verify_fun that accepts the unknown ca error"];
+unknown_server_ca_accept_verify_peer(suite) ->
+ [];
+unknown_server_ca_accept_verify_peer(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE,
+ send_recv_result_active, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ FunAndState = {fun(_,{bad_cert, unknown_ca}, UserState) ->
+ {valid, UserState};
+ (_,{bad_cert, _} = Reason, _) ->
+ {fail, Reason};
+ (_,{extension, _}, UserState) ->
+ {unknown, UserState};
+ (_, valid, UserState) ->
+ {valid, UserState};
+ (_, valid_peer, UserState) ->
+ {valid, UserState}
+ end, []},
+
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE,
+ send_recv_result_active, []}},
+ {options,
+ [{verify, verify_peer},
+ {verify_fun, FunAndState}| ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+unknown_server_ca_accept_backwardscompatibilty(doc) ->
+ ["Test that old style verify_funs will work"];
+unknown_server_ca_accept_backwardscompatibilty(suite) ->
+ [];
+unknown_server_ca_accept_backwardscompatibilty(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE,
+ send_recv_result_active, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ AcceptBadCa = fun({bad_cert,unknown_ca}, Acc) -> Acc;
+ (Other, Acc) -> [Other | Acc]
+ end,
+ VerifyFun =
+ fun(ErrorList) ->
+ case lists:foldl(AcceptBadCa, [], ErrorList) of
+ [] -> true;
+ [_|_] -> false
+ end
+ end,
+
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE,
+ send_recv_result_active, []}},
+ {options,
+ [{verify, verify_peer},
+ {verify_fun, VerifyFun}| ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+der_input(doc) ->
+ ["Test to input certs and key as der"];
+
+der_input(suite) ->
+ [];
+
+der_input(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ DHParamFile = filename:join(DataDir, "dHParam.pem"),
+
+ SeverVerifyOpts = ?config(server_verification_opts, Config),
+ {ServerCert, ServerKey, ServerCaCerts, DHParams} = der_input_opts([{dhfile, DHParamFile} |
+ SeverVerifyOpts]),
+ ClientVerifyOpts = ?config(client_verification_opts, Config),
+ {ClientCert, ClientKey, ClientCaCerts, DHParams} = der_input_opts([{dhfile, DHParamFile} |
+ ClientVerifyOpts]),
+ ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true},
+ {dh, DHParams},
+ {cert, ServerCert}, {key, ServerKey}, {cacerts, ServerCaCerts}],
+ ClientOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true},
+ {dh, DHParams},
+ {cert, ClientCert}, {key, ClientKey}, {cacerts, ClientCaCerts}],
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, send_recv_result, []}},
+ {options, [{active, false} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, send_recv_result, []}},
+ {options, [{active, false} | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+der_input_opts(Opts) ->
+ Certfile = proplists:get_value(certfile, Opts),
+ CaCertsfile = proplists:get_value(cacertfile, Opts),
+ Keyfile = proplists:get_value(keyfile, Opts),
+ Dhfile = proplists:get_value(dhfile, Opts),
+ [{_, Cert, _}] = ssl_test_lib:pem_to_der(Certfile),
+ [{_, Key, _}] = ssl_test_lib:pem_to_der(Keyfile),
+ [{_, DHParams, _}] = ssl_test_lib:pem_to_der(Dhfile),
+ CaCerts =
+ lists:map(fun(Entry) ->
+ {_, CaCert, _} = Entry,
+ CaCert
+ end, ssl_test_lib:pem_to_der(CaCertsfile)),
+ {Cert, {rsa, Key}, CaCerts, DHParams}.
+
+%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
+erlang_ssl_receive(Socket, Data) ->
+ receive
+ {ssl, Socket, Data} ->
+ io:format("Received ~p~n",[Data]),
+ ok;
+ Other ->
+ test_server:fail({unexpected_message, Other})
+ after ?SLEEP * 3 ->
+ test_server:fail({did_not_get, Data})
+ end.
+
send_recv_result(Socket) ->
ssl:send(Socket, "Hello world"),
{ok,"Hello world"} = ssl:recv(Socket, 11),
@@ -2873,6 +3086,7 @@ send_recv_result_active_once(Socket) ->
result_ok(_Socket) ->
ok.
+
renegotiate(Socket, Data) ->
test_server:format("Renegotiating ~n", []),
Result = ssl:renegotiate(Socket),
@@ -2889,162 +3103,3 @@ renegotiate_reuse_session(Socket, Data) ->
%% Make sure session is registerd
test_server:sleep(?SLEEP),
renegotiate(Socket, Data).
-
-session_cache_process_list(doc) ->
- ["Test reuse of sessions (short handshake)"];
-
-session_cache_process_list(suite) ->
- [];
-session_cache_process_list(Config) when is_list(Config) ->
- session_cache_process(list,Config).
-
-session_cache_process_mnesia(doc) ->
- ["Test reuse of sessions (short handshake)"];
-
-session_cache_process_mnesia(suite) ->
- [];
-session_cache_process_mnesia(Config) when is_list(Config) ->
- session_cache_process(mnesia,Config).
-
-session_cache_process(Type,Config) when is_list(Config) ->
- reuse_session(Config).
-
-init([Type]) ->
- ets:new(ssl_test, [named_table, public, set]),
- ets:insert(ssl_test, {type, Type}),
- case Type of
- list ->
- spawn(fun() -> session_loop([]) end);
- mnesia ->
- mnesia:start(),
- {atomic,ok} = mnesia:create_table(sess_cache, []),
- sess_cache
- end.
-
-session_cb() ->
- [{type, Type}] = ets:lookup(ssl_test, type),
- Type.
-
-terminate(Cache) ->
- case session_cb() of
- list ->
- Cache ! terminate;
- mnesia ->
- catch {atomic,ok} =
- mnesia:delete_table(sess_cache)
- end.
-
-lookup(Cache, Key) ->
- case session_cb() of
- list ->
- Cache ! {self(), lookup, Key},
- receive {Cache, Res} -> Res end;
- mnesia ->
- case mnesia:transaction(fun() ->
- mnesia:read(sess_cache,
- Key, read)
- end) of
- {atomic, [{sess_cache, Key, Value}]} ->
- Value;
- _ ->
- undefined
- end
- end.
-
-update(Cache, Key, Value) ->
- case session_cb() of
- list ->
- Cache ! {update, Key, Value};
- mnesia ->
- {atomic, ok} =
- mnesia:transaction(fun() ->
- mnesia:write(sess_cache,
- {sess_cache, Key, Value}, write)
- end)
- end.
-
-delete(Cache, Key) ->
- case session_cb() of
- list ->
- Cache ! {delete, Key};
- mnesia ->
- {atomic, ok} =
- mnesia:transaction(fun() ->
- mnesia:delete(sess_cache, Key)
- end)
- end.
-
-foldl(Fun, Acc, Cache) ->
- case session_cb() of
- list ->
- Cache ! {self(),foldl,Fun,Acc},
- receive {Cache, Res} -> Res end;
- mnesia ->
- Foldl = fun() ->
- mnesia:foldl(Fun, Acc, sess_cache)
- end,
- {atomic, Res} = mnesia:transaction(Foldl),
- Res
- end.
-
-select_session(Cache, PartialKey) ->
- case session_cb() of
- list ->
- Cache ! {self(),select_session, PartialKey},
- receive
- {Cache, Res} ->
- Res
- end;
- mnesia ->
- Sel = fun() ->
- mnesia:select(Cache,
- [{{sess_cache,{PartialKey,'$1'}, '$2'},
- [],['$$']}])
- end,
- {atomic, Res} = mnesia:transaction(Sel),
- Res
- end.
-
-session_loop(Sess) ->
- receive
- terminate ->
- ok;
- {Pid, lookup, Key} ->
- case lists:keysearch(Key,1,Sess) of
- {value, {Key,Value}} ->
- Pid ! {self(), Value};
- _ ->
- Pid ! {self(), undefined}
- end,
- session_loop(Sess);
- {update, Key, Value} ->
- NewSess = [{Key,Value}| lists:keydelete(Key,1,Sess)],
- session_loop(NewSess);
- {delete, Key} ->
- session_loop(lists:keydelete(Key,1,Sess));
- {Pid,foldl,Fun,Acc} ->
- Res = lists:foldl(Fun, Acc,Sess),
- Pid ! {self(), Res},
- session_loop(Sess);
- {Pid,select_session,PKey} ->
- Sel = fun({{PKey0, Id},Session}, Acc) when PKey == PKey0 ->
- [[Id, Session]|Acc];
- (_,Acc) ->
- Acc
- end,
- Sessions = lists:foldl(Sel, [], Sess),
- Pid ! {self(), Sessions},
- session_loop(Sess)
- end.
-
-
-erlang_ssl_receive(Socket, Data) ->
- receive
- {ssl, Socket, Data} ->
- io:format("Received ~p~n",[Data]),
- ok;
- Other ->
- test_server:fail({unexpected_message, Other})
- after ?SLEEP * 3 ->
- test_server:fail({did_not_get, Data})
- end.
diff --git a/lib/ssl/test/ssl_packet_SUITE.erl b/lib/ssl/test/ssl_packet_SUITE.erl
index 1b8754afe9..88d2d99ef8 100644
--- a/lib/ssl/test/ssl_packet_SUITE.erl
+++ b/lib/ssl/test/ssl_packet_SUITE.erl
@@ -145,14 +145,20 @@ all(suite) ->
packet_baddata_passive, packet_baddata_active,
packet_size_passive, packet_size_active,
packet_cdr_decode,
+ packet_cdr_decode_list,
packet_http_decode,
packet_http_decode_list,
packet_http_bin_decode_multi,
+ packet_http_error_passive,
packet_line_decode,
- packet_asn1_decode,
+ packet_line_decode_list,
+ packet_asn1_decode,
+ packet_asn1_decode_list,
packet_tpkt_decode,
+ packet_tpkt_decode_list,
%packet_fcgi_decode,
packet_sunrm_decode,
+ packet_sunrm_decode_list,
header_decode_one_byte,
header_decode_two_bytes,
header_decode_two_bytes_one_sent,
@@ -1429,7 +1435,7 @@ packet_size_passive(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
packet_cdr_decode(doc) ->
- ["Test setting the packet option {packet, cdr}"];
+ ["Test setting the packet option {packet, cdr}, {mode, binary}"];
packet_cdr_decode(suite) ->
[];
packet_cdr_decode(Config) when is_list(Config) ->
@@ -1463,8 +1469,44 @@ packet_cdr_decode(Config) when is_list(Config) ->
ssl_test_lib:close(Client).
%%--------------------------------------------------------------------
+packet_cdr_decode_list(doc) ->
+ ["Test setting the packet option {packet, cdr} {mode, list}"];
+packet_cdr_decode_list(suite) ->
+ [];
+packet_cdr_decode_list(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ %% A valid cdr packet
+ Data = [71,73,79,80,1,2,2,1,0,0,0,41,0,0,0,0,0,0,0,0,0,0,0,1,78,
+ 69,79,0,0,0,0,2,0,10,0,0,0,0,0,0,0,0,0,18,0,0,0,0,0,0,0,4,49],
+
+ Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, server_packet_decode,
+ [Data]}},
+ {options, [{active, true}, list,
+ {packet, cdr}|ServerOpts]}]),
+
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, client_packet_decode,
+ [Data]}},
+ {options, [{active, true}, {packet, cdr},
+ list | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
packet_http_decode(doc) ->
- ["Test setting the packet option {packet, http} {mode, binary}"];
+ ["Test setting the packet option {packet, http} {mode, binary} "
+ "(Body will be binary http strings are lists)"];
packet_http_decode(suite) ->
[];
@@ -1485,7 +1527,7 @@ packet_http_decode(Config) when is_list(Config) ->
{from, self()},
{mfa, {?MODULE, server_http_decode,
[Response]}},
- {options, [{active, true}, binary,
+ {options, [{active, true},binary,
{packet, http} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
@@ -1494,7 +1536,7 @@ packet_http_decode(Config) when is_list(Config) ->
{from, self()},
{mfa, {?MODULE, client_http_decode,
[Request]}},
- {options, [{active, true}, binary,
+ {options, [{active, true}, binary,
{packet, http} |
ClientOpts]}]),
@@ -1548,7 +1590,8 @@ client_http_decode(Socket, HttpRequest) ->
%%--------------------------------------------------------------------
packet_http_decode_list(doc) ->
- ["Test setting the packet option {packet, http}, {mode, list}"];
+ ["Test setting the packet option {packet, http}, {mode, list}"
+ "(Body will be litst too)"];
packet_http_decode_list(suite) ->
[];
packet_http_decode_list(Config) when is_list(Config) ->
@@ -1695,9 +1738,74 @@ client_http_bin_decode(Socket, HttpRequest, Count) when Count > 0 ->
client_http_bin_decode(Socket, HttpRequest, Count - 1);
client_http_bin_decode(_, _, _) ->
ok.
+
+%%--------------------------------------------------------------------
+packet_http_error_passive(doc) ->
+ ["Test setting the packet option {packet, http}, {active, false}"
+ " with a incorrect http header." ];
+packet_http_error_passive(suite) ->
+ [];
+packet_http_error_passive(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Request = "GET / HTTP/1.1\r\n"
+ "host: www.example.com\r\n"
+ "user-agent HttpTester\r\n"
+ "\r\n",
+ Response = "HTTP/1.1 200 OK\r\n"
+ "\r\n"
+ "Hello!",
+
+ Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, server_http_decode_error,
+ [Response]}},
+ {options, [{active, false}, binary,
+ {packet, http} |
+ ServerOpts]}]),
+
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, client_http_decode_list,
+ [Request]}},
+ {options, [{active, true}, list,
+ {packet, http} |
+ ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+
+server_http_decode_error(Socket, HttpResponse) ->
+ assert_packet_opt(Socket, http),
+
+ {ok, {http_request, 'GET', _, {1,1}}} = ssl:recv(Socket, 0),
+
+ assert_packet_opt(Socket, http),
+
+ {ok, {http_header, _, 'Host', _, "www.example.com"}} = ssl:recv(Socket, 0),
+ assert_packet_opt(Socket, http),
+
+ {ok, {http_error, _}} = ssl:recv(Socket, 0),
+
+ assert_packet_opt(Socket, http),
+
+ {ok, http_eoh} = ssl:recv(Socket, 0),
+
+ assert_packet_opt(Socket, http),
+ ok = ssl:send(Socket, HttpResponse),
+ ok.
+
+
%%--------------------------------------------------------------------
packet_line_decode(doc) ->
- ["Test setting the packet option {packet, line}"];
+ ["Test setting the packet option {packet, line}, {mode, binary}"];
packet_line_decode(suite) ->
[];
packet_line_decode(Config) when is_list(Config) ->
@@ -1731,30 +1839,44 @@ packet_line_decode(Config) when is_list(Config) ->
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
+%%--------------------------------------------------------------------
-server_line_packet_decode(Socket, Lines) ->
- receive
- {ssl, Socket, <<"Line ends here.\n">>} -> ok;
- Other1 -> exit({?LINE, Other1})
- end,
- receive
- {ssl, Socket, <<"Now it is a new line.\n">>} -> ok;
- Other2 -> exit({?LINE, Other2})
- end,
- ok = ssl:send(Socket, Lines).
+packet_line_decode_list(doc) ->
+ ["Test setting the packet option {packet, line}, {mode, list}"];
+packet_line_decode_list(suite) ->
+ [];
+packet_line_decode_list(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Data = lists:flatten(io_lib:format("Line ends here.~n"
+ "Now it is a new line.~n", [])),
+
+ Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE,
+ server_line_packet_decode,
+ [Data]}},
+ {options, [{active, true}, list,
+ {packet, line}|ServerOpts]}]),
+
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE,
+ client_line_packet_decode,
+ [Data]}},
+ {options, [{active, true},
+ {packet, line},
+ list | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
-client_line_packet_decode(Socket, Lines) ->
- <<P1:10/binary, P2/binary>> = Lines,
- ok = ssl:send(Socket, P1),
- ok = ssl:send(Socket, P2),
- receive
- {ssl, Socket, <<"Line ends here.\n">>} -> ok;
- Other1 -> exit({?LINE, Other1})
- end,
- receive
- {ssl, Socket, <<"Now it is a new line.\n">>} -> ok;
- Other2 -> exit({?LINE, Other2})
- end.
%%--------------------------------------------------------------------
@@ -1770,7 +1892,7 @@ packet_asn1_decode(Config) when is_list(Config) ->
File = proplists:get_value(certfile, ServerOpts),
%% A valid asn1 BER packet (DER is stricter BER)
- {ok,[{cert, Data, _}]} = public_key:pem_to_der(File),
+ [{'Certificate', Data, _}] = ssl_test_lib:pem_to_der(File),
Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
{from, self()},
@@ -1794,6 +1916,44 @@ packet_asn1_decode(Config) when is_list(Config) ->
ssl_test_lib:close(Client).
%%--------------------------------------------------------------------
+packet_asn1_decode_list(doc) ->
+ ["Test setting the packet option {packet, asn1}"];
+packet_asn1_decode_list(suite) ->
+ [];
+packet_asn1_decode_list(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ File = proplists:get_value(certfile, ServerOpts),
+
+ %% A valid asn1 BER packet (DER is stricter BER)
+ [{'Certificate', BinData, _}] = ssl_test_lib:pem_to_der(File),
+
+ Data = binary_to_list(BinData),
+
+ Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, server_packet_decode,
+ [Data]}},
+ {options, [{active, true}, list,
+ {packet, asn1}|ServerOpts]}]),
+
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, client_packet_decode,
+ [Data]}},
+ {options, [{active, true}, {packet, asn1},
+ list | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
packet_tpkt_decode(doc) ->
["Test setting the packet option {packet, tpkt}"];
packet_tpkt_decode(suite) ->
@@ -1826,6 +1986,38 @@ packet_tpkt_decode(Config) when is_list(Config) ->
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
+%%--------------------------------------------------------------------
+packet_tpkt_decode_list(doc) ->
+ ["Test setting the packet option {packet, tpkt}"];
+packet_tpkt_decode_list(suite) ->
+ [];
+packet_tpkt_decode_list(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Data = binary_to_list(list_to_binary(add_tpkt_header("TPKT data"))),
+
+ Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, server_packet_decode,
+ [Data]}},
+ {options, [{active, true}, list,
+ {packet, tpkt}|ServerOpts]}]),
+
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, client_packet_decode,
+ [Data]}},
+ {options, [{active, true}, {packet, tpkt},
+ list | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
%%--------------------------------------------------------------------
@@ -1895,6 +2087,39 @@ packet_sunrm_decode(Config) when is_list(Config) ->
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+packet_sunrm_decode_list(doc) ->
+ ["Test setting the packet option {packet, sunrm}"];
+packet_sunrm_decode_list(suite) ->
+ [];
+packet_sunrm_decode_list(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Data = binary_to_list(list_to_binary([<<11:32>>, "Hello world"])),
+
+ Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, server_packet_decode,
+ [Data]}},
+ {options, [{active, true}, list,
+ {packet, sunrm}|ServerOpts]}]),
+
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, client_packet_decode,
+ [Data]}},
+ {options, [{active, true}, {packet, sunrm},
+ list | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
%%--------------------------------------------------------------------
header_decode_one_byte(doc) ->
@@ -2037,21 +2262,29 @@ header_decode_two_bytes_one_sent(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
%% Internal functions
-send_raw(_,_, 0) ->
+send_raw(Socket,_, 0) ->
+ ssl:send(Socket, <<>>),
no_result_msg;
send_raw(Socket, Data, N) ->
ssl:send(Socket, Data),
send_raw(Socket, Data, N-1).
-passive_raw(_, _, 0) ->
+passive_raw(Socket, _, 0) ->
+ {error, timeout} = ssl:recv(Socket, 0, 500),
ok;
passive_raw(Socket, Data, N) ->
Length = length(Data),
{ok, Data} = ssl:recv(Socket, Length),
passive_raw(Socket, Data, N-1).
-passive_recv_packet(_, _, 0) ->
- ok;
+passive_recv_packet(Socket, _, 0) ->
+ case ssl:recv(Socket, 0) of
+ {ok, []} ->
+ {error, timeout} = ssl:recv(Socket, 0, 500),
+ ok;
+ Other ->
+ {other, Other, ssl:session_info(Socket), 0}
+ end;
passive_recv_packet(Socket, Data, N) ->
case ssl:recv(Socket, 0) of
{ok, Data} ->
@@ -2060,7 +2293,8 @@ passive_recv_packet(Socket, Data, N) ->
{other, Other, ssl:session_info(Socket), N}
end.
-send(_,_, 0) ->
+send(Socket,_, 0) ->
+ ssl:send(Socket, <<>>),
no_result_msg;
send(Socket, Data, N) ->
case ssl:send(Socket, [Data]) of
@@ -2074,6 +2308,7 @@ send_incomplete(Socket, Data, N) ->
send_incomplete(Socket, Data, N, <<>>).
send_incomplete(Socket, _Data, 0, Prev) ->
ssl:send(Socket, Prev),
+ ssl:send(Socket, [?uint32(0)]),
no_result_msg;
send_incomplete(Socket, Data, N, Prev) ->
Length = size(Data),
@@ -2102,8 +2337,13 @@ active_once_raw(Socket, Data, N, Acc) ->
end
end.
-active_once_packet(_,_, 0) ->
- ok;
+active_once_packet(Socket,_, 0) ->
+ receive
+ {ssl, Socket, []} ->
+ ok;
+ {ssl, Socket, Other} ->
+ {other, Other, ssl:session_info(Socket), 0}
+ end;
active_once_packet(Socket, Data, N) ->
receive
{ssl, Socket, Data} ->
@@ -2115,7 +2355,7 @@ active_once_packet(Socket, Data, N) ->
active_raw(Socket, Data, N) ->
active_raw(Socket, Data, N, []).
-active_raw(_, _, 0, _) ->
+active_raw(_Socket, _, 0, _) ->
ok;
active_raw(Socket, Data, N, Acc) ->
receive
@@ -2130,8 +2370,13 @@ active_raw(Socket, Data, N, Acc) ->
end
end.
-active_packet(_, _, 0) ->
- ok;
+active_packet(Socket, _, 0) ->
+ receive
+ {ssl, Socket, []} ->
+ ok;
+ Other ->
+ {other, Other, ssl:session_info(Socket), 0}
+ end;
active_packet(Socket, Data, N) ->
receive
{ssl, Socket, Data} ->
@@ -2155,8 +2400,14 @@ server_packet_decode(Socket, Packet) ->
end,
ok = ssl:send(Socket, Packet).
-client_packet_decode(Socket, Packet) ->
+client_packet_decode(Socket, Packet) when is_binary(Packet)->
<<P1:10/binary, P2/binary>> = Packet,
+ client_packet_decode(Socket, P1, P2, Packet);
+client_packet_decode(Socket, [Head | Tail] = Packet) ->
+ client_packet_decode(Socket, [Head], Tail, Packet).
+
+client_packet_decode(Socket, P1, P2, Packet) ->
+ test_server:format("Packet: ~p ~n", [Packet]),
ok = ssl:send(Socket, P1),
ok = ssl:send(Socket, P2),
receive
@@ -2176,7 +2427,7 @@ server_header_decode(Socket, Packet, Result) ->
end,
ok = ssl:send(Socket, Packet),
receive
- {ssl, Socket, Result} -> ok;
+ {ssl, Socket, Result} -> ok;
Other2 -> exit({?LINE, Other2})
end,
ok = ssl:send(Socket, Packet).
@@ -2192,6 +2443,44 @@ client_header_decode(Socket, Packet, Result) ->
{ssl, Socket, Result} -> ok;
Other2 -> exit({?LINE, Other2})
end.
+
+server_line_packet_decode(Socket, Packet) when is_binary(Packet) ->
+ [L1, L2] = string:tokens(binary_to_list(Packet), "\n"),
+ server_line_packet_decode(Socket, list_to_binary(L1 ++ "\n"), list_to_binary(L2 ++ "\n"), Packet);
+server_line_packet_decode(Socket, Packet) ->
+ [L1, L2] = string:tokens(Packet, "\n"),
+ server_line_packet_decode(Socket, L1 ++ "\n", L2 ++ "\n", Packet).
+
+server_line_packet_decode(Socket, L1, L2, Packet) ->
+ receive
+ {ssl, Socket, L1} -> ok;
+ Other1 -> exit({?LINE, Other1})
+ end,
+ receive
+ {ssl, Socket, L2} -> ok;
+ Other2 -> exit({?LINE, Other2})
+ end,
+ ok = ssl:send(Socket, Packet).
+
+client_line_packet_decode(Socket, Packet) when is_binary(Packet)->
+ <<P1:10/binary, P2/binary>> = Packet,
+ [L1, L2] = string:tokens(binary_to_list(Packet), "\n"),
+ client_line_packet_decode(Socket, P1, P2, list_to_binary(L1 ++ "\n"), list_to_binary(L2 ++ "\n"));
+client_line_packet_decode(Socket, [Head | Tail] = Packet) ->
+ [L1, L2] = string:tokens(Packet, "\n"),
+ client_line_packet_decode(Socket, [Head], Tail, L1 ++ "\n", L2 ++ "\n").
+
+client_line_packet_decode(Socket, P1, P2, L1, L2) ->
+ ok = ssl:send(Socket, P1),
+ ok = ssl:send(Socket, P2),
+ receive
+ {ssl, Socket, L1} -> ok;
+ Other1 -> exit({?LINE, Other1})
+ end,
+ receive
+ {ssl, Socket, L2} -> ok;
+ Other2 -> exit({?LINE, Other2})
+ end.
add_tpkt_header(Data) when is_binary(Data) ->
L = size(Data) + 4,
diff --git a/lib/ssl/test/ssl_session_cache_SUITE.erl b/lib/ssl/test/ssl_session_cache_SUITE.erl
new file mode 100644
index 0000000000..7a441e4599
--- /dev/null
+++ b/lib/ssl/test/ssl_session_cache_SUITE.erl
@@ -0,0 +1,305 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.2
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(ssl_session_cache_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include("test_server.hrl").
+
+-define(SLEEP, 500).
+-define(TIMEOUT, 60000).
+-behaviour(ssl_session_cache_api).
+
+%% For the session cache tests
+-export([init/1, terminate/1, lookup/2, update/3,
+ delete/2, foldl/3, select_session/2]).
+
+%% Test server callback functions
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config) -> Config
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Description: Initialization before the whole suite
+%%
+%% Note: This function is free to add any key/value pairs to the Config
+%% variable, but should NOT alter/remove any existing entries.
+%%--------------------------------------------------------------------
+init_per_suite(Config0) ->
+ Dog = ssl_test_lib:timetrap(?TIMEOUT *2),
+ crypto:start(),
+ application:start(public_key),
+ ssl:start(),
+
+ %% make rsa certs using oppenssl
+ Result =
+ (catch make_certs:all(?config(data_dir, Config0),
+ ?config(priv_dir, Config0))),
+ test_server:format("Make certs ~p~n", [Result]),
+
+ Config1 = ssl_test_lib:make_dsa_cert(Config0),
+ Config = ssl_test_lib:cert_options(Config1),
+ [{watchdog, Dog} | Config].
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config) -> _
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Description: Cleanup after the whole suite
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ssl:stop(),
+ crypto:stop().
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config) -> Config
+%% Case - atom()
+%% Name of the test case that is about to be run.
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%%
+%% Description: Initialization before each test case
+%%
+%% Note: This function is free to add any key/value pairs to the Config
+%% variable, but should NOT alter/remove any existing entries.
+%% Description: Initialization before each test case
+%%--------------------------------------------------------------------
+init_per_testcase(session_cache_process_list, Config) ->
+ init_customized_session_cache(list, Config);
+
+init_per_testcase(session_cache_process_mnesia, Config) ->
+ mnesia:start(),
+ init_customized_session_cache(mnesia, Config);
+
+init_per_testcase(_TestCase, Config0) ->
+ Config = lists:keydelete(watchdog, 1, Config0),
+ Dog = test_server:timetrap(?TIMEOUT),
+ [{watchdog, Dog} | Config].
+
+init_customized_session_cache(Type, Config0) ->
+ Config = lists:keydelete(watchdog, 1, Config0),
+ Dog = test_server:timetrap(?TIMEOUT),
+ ssl:stop(),
+ application:load(ssl),
+ application:set_env(ssl, session_cb, ?MODULE),
+ application:set_env(ssl, session_cb_init_args, [Type]),
+ ssl:start(),
+ [{watchdog, Dog} | Config].
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config) -> _
+%% Case - atom()
+%% Name of the test case that is about to be run.
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Description: Cleanup after each test case
+%%--------------------------------------------------------------------
+end_per_testcase(session_cache_process_list, Config) ->
+ application:unset_env(ssl, session_cb),
+ end_per_testcase(default_action, Config);
+end_per_testcase(session_cache_process_mnesia, Config) ->
+ application:unset_env(ssl, session_cb),
+ application:unset_env(ssl, session_cb_init_args),
+ mnesia:stop(),
+ ssl:stop(),
+ ssl:start(),
+ end_per_testcase(default_action, Config);
+end_per_testcase(_TestCase, Config) ->
+ Dog = ?config(watchdog, Config),
+ case Dog of
+ undefined ->
+ ok;
+ _ ->
+ test_server:timetrap_cancel(Dog)
+ end.
+
+%%--------------------------------------------------------------------
+%% Function: all(Clause) -> TestCases
+%% Clause - atom() - suite | doc
+%% TestCases - [Case]
+%% Case - atom()
+%% Name of a test case.
+%% Description: Returns a list of all test cases in this test suite
+%%--------------------------------------------------------------------
+all(doc) ->
+ ["Test session cach API"];
+
+all(suite) ->
+ [
+ session_cache_process_list, session_cache_process_mnesia
+ ].
+
+session_cache_process_list(doc) ->
+ ["Test reuse of sessions (short handshake)"];
+
+session_cache_process_list(suite) ->
+ [];
+session_cache_process_list(Config) when is_list(Config) ->
+ session_cache_process(list,Config).
+%%--------------------------------------------------------------------
+session_cache_process_mnesia(doc) ->
+ ["Test reuse of sessions (short handshake)"];
+
+session_cache_process_mnesia(suite) ->
+ [];
+session_cache_process_mnesia(Config) when is_list(Config) ->
+ session_cache_process(mnesia,Config).
+
+
+%%--------------------------------------------------------------------
+%%% Session cache API callbacks
+%%--------------------------------------------------------------------
+
+init([Type]) ->
+ ets:new(ssl_test, [named_table, public, set]),
+ ets:insert(ssl_test, {type, Type}),
+ case Type of
+ list ->
+ spawn(fun() -> session_loop([]) end);
+ mnesia ->
+ mnesia:start(),
+ {atomic,ok} = mnesia:create_table(sess_cache, []),
+ sess_cache
+ end.
+
+session_cb() ->
+ [{type, Type}] = ets:lookup(ssl_test, type),
+ Type.
+
+terminate(Cache) ->
+ case session_cb() of
+ list ->
+ Cache ! terminate;
+ mnesia ->
+ catch {atomic,ok} =
+ mnesia:delete_table(sess_cache)
+ end.
+
+lookup(Cache, Key) ->
+ case session_cb() of
+ list ->
+ Cache ! {self(), lookup, Key},
+ receive {Cache, Res} -> Res end;
+ mnesia ->
+ case mnesia:transaction(fun() ->
+ mnesia:read(sess_cache,
+ Key, read)
+ end) of
+ {atomic, [{sess_cache, Key, Value}]} ->
+ Value;
+ _ ->
+ undefined
+ end
+ end.
+
+update(Cache, Key, Value) ->
+ case session_cb() of
+ list ->
+ Cache ! {update, Key, Value};
+ mnesia ->
+ {atomic, ok} =
+ mnesia:transaction(fun() ->
+ mnesia:write(sess_cache,
+ {sess_cache, Key, Value}, write)
+ end)
+ end.
+
+delete(Cache, Key) ->
+ case session_cb() of
+ list ->
+ Cache ! {delete, Key};
+ mnesia ->
+ {atomic, ok} =
+ mnesia:transaction(fun() ->
+ mnesia:delete(sess_cache, Key)
+ end)
+ end.
+
+foldl(Fun, Acc, Cache) ->
+ case session_cb() of
+ list ->
+ Cache ! {self(),foldl,Fun,Acc},
+ receive {Cache, Res} -> Res end;
+ mnesia ->
+ Foldl = fun() ->
+ mnesia:foldl(Fun, Acc, sess_cache)
+ end,
+ {atomic, Res} = mnesia:transaction(Foldl),
+ Res
+ end.
+
+select_session(Cache, PartialKey) ->
+ case session_cb() of
+ list ->
+ Cache ! {self(),select_session, PartialKey},
+ receive
+ {Cache, Res} ->
+ Res
+ end;
+ mnesia ->
+ Sel = fun() ->
+ mnesia:select(Cache,
+ [{{sess_cache,{PartialKey,'$1'}, '$2'},
+ [],['$$']}])
+ end,
+ {atomic, Res} = mnesia:transaction(Sel),
+ Res
+ end.
+
+session_loop(Sess) ->
+ receive
+ terminate ->
+ ok;
+ {Pid, lookup, Key} ->
+ case lists:keysearch(Key,1,Sess) of
+ {value, {Key,Value}} ->
+ Pid ! {self(), Value};
+ _ ->
+ Pid ! {self(), undefined}
+ end,
+ session_loop(Sess);
+ {update, Key, Value} ->
+ NewSess = [{Key,Value}| lists:keydelete(Key,1,Sess)],
+ session_loop(NewSess);
+ {delete, Key} ->
+ session_loop(lists:keydelete(Key,1,Sess));
+ {Pid,foldl,Fun,Acc} ->
+ Res = lists:foldl(Fun, Acc,Sess),
+ Pid ! {self(), Res},
+ session_loop(Sess);
+ {Pid,select_session,PKey} ->
+ Sel = fun({{PKey0, Id},Session}, Acc) when PKey == PKey0 ->
+ [[Id, Session]|Acc];
+ (_,Acc) ->
+ Acc
+ end,
+ Sessions = lists:foldl(Sel, [], Sess),
+ Pid ! {self(), Sessions},
+ session_loop(Sess)
+ end.
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+
+session_cache_process(_Type,Config) when is_list(Config) ->
+ ssl_basic_SUITE:reuse_session(Config).
diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl
index dd0818827a..e1e8214ed6 100644
--- a/lib/ssl/test/ssl_test_lib.erl
+++ b/lib/ssl/test/ssl_test_lib.erl
@@ -268,6 +268,8 @@ cert_options(Config) ->
"client", "cacerts.pem"]),
ClientCertFile = filename:join([?config(priv_dir, Config),
"client", "cert.pem"]),
+ ClientCertFileDigitalSignatureOnly = filename:join([?config(priv_dir, Config),
+ "client", "digital_signature_only_cert.pem"]),
ServerCaCertFile = filename:join([?config(priv_dir, Config),
"server", "cacerts.pem"]),
ServerCertFile = filename:join([?config(priv_dir, Config),
@@ -292,8 +294,13 @@ cert_options(Config) ->
{certfile, ClientCertFile},
{keyfile, ClientKeyFile},
{ssl_imp, new}]},
+ {client_verification_opts_digital_signature_only, [{cacertfile, ClientCaCertFile},
+ {certfile, ClientCertFileDigitalSignatureOnly},
+ {keyfile, ClientKeyFile},
+ {ssl_imp, new}]},
{server_opts, [{ssl_imp, new},{reuseaddr, true},
{certfile, ServerCertFile}, {keyfile, ServerKeyFile}]},
+ {server_anon, [{ssl_imp, new},{reuseaddr, true}, {ciphers, anonymous_suites()}]},
{server_verification_opts, [{ssl_imp, new},{reuseaddr, true},
{cacertfile, ServerCaCertFile},
{certfile, ServerCertFile}, {keyfile, ServerKeyFile}]},
@@ -326,7 +333,7 @@ make_dsa_cert(Config) ->
{cacertfile, ServerCaCertFile},
{certfile, ServerCertFile}, {keyfile, ServerKeyFile}]},
{server_dsa_verify_opts, [{ssl_imp, new},{reuseaddr, true},
- {cacertfile, ServerCaCertFile},
+ {cacertfile, ClientCaCertFile},
{certfile, ServerCertFile}, {keyfile, ServerKeyFile},
{verify, verify_peer}]},
{client_dsa_opts, [{ssl_imp, new},{reuseaddr, true},
@@ -346,9 +353,9 @@ make_dsa_cert_files(RoleStr, Config) ->
KeyFile = filename:join([?config(priv_dir, Config),
RoleStr, "dsa_key.pem"]),
- public_key:der_to_pem(CaCertFile, [{cert, CaCert, not_encrypted}]),
- public_key:der_to_pem(CertFile, [{cert, Cert, not_encrypted}]),
- public_key:der_to_pem(KeyFile, [CertKey]),
+ der_to_pem(CaCertFile, [{'Certificate', CaCert, not_encrypted}]),
+ der_to_pem(CertFile, [{'Certificate', Cert, not_encrypted}]),
+ der_to_pem(KeyFile, [CertKey]),
{CaCertFile, CertFile, KeyFile}.
start_upgrade_server(Args) ->
@@ -571,6 +578,14 @@ rsa_suites() ->
end,
ssl:cipher_suites()).
+rsa_non_signed_suites() ->
+ lists:filter(fun({rsa, _, _}) ->
+ true;
+ (_) ->
+ false
+ end,
+ ssl:cipher_suites()).
+
dsa_suites() ->
lists:filter(fun({dhe_dss, _, _}) ->
true;
@@ -601,3 +616,35 @@ openssl_dsa_suites() ->
true
end
end, Ciphers).
+
+anonymous_suites() ->
+ [{dh_anon, rc4_128, md5},
+ {dh_anon, des_cbc, sha},
+ {dh_anon, '3des_ede_cbc', sha},
+ {dh_anon, aes_128_cbc, sha},
+ {dh_anon, aes_256_cbc, sha}].
+
+pem_to_der(File) ->
+ {ok, PemBin} = file:read_file(File),
+ public_key:pem_decode(PemBin).
+
+der_to_pem(File, Entries) ->
+ PemBin = public_key:pem_encode(Entries),
+ file:write_file(File, PemBin).
+
+cipher_result(Socket, Result) ->
+ Result = ssl:connection_info(Socket),
+ test_server:format("Successfull connect: ~p~n", [Result]),
+ %% Importante to send two packets here
+ %% to properly test "cipher state" handling
+ ssl:send(Socket, "Hello\n"),
+ receive
+ {ssl, Socket, "Hello\n"} ->
+ ssl:send(Socket, " world\n"),
+ receive
+ {ssl, Socket, " world\n"} ->
+ ok
+ end;
+ Other ->
+ {unexpected, Other}
+ end.
diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl
index 75cfce0052..55a0100b1e 100644
--- a/lib/ssl/test/ssl_to_openssl_SUITE.erl
+++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl
@@ -1116,8 +1116,6 @@ run_suites(Ciphers, Version, Config, Type) ->
test_server:fail(cipher_suite_failed_see_test_case_log)
end.
-
-
cipher(CipherSuite, Version, Config, ClientOpts, ServerOpts) ->
process_flag(trap_exit, true),
test_server:format("Testing CipherSuite ~p~n", [CipherSuite]),
@@ -1128,25 +1126,39 @@ cipher(CipherSuite, Version, Config, ClientOpts, ServerOpts) ->
KeyFile = proplists:get_value(keyfile, ServerOpts),
Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++
- " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ "",
-
+ " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ "",
+
test_server:format("openssl cmd: ~p~n", [Cmd]),
OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
wait_for_openssl_server(),
+ ConnectionInfo = {ok, {Version, CipherSuite}},
+
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
- {from, self()},
- {mfa, {?MODULE, connection_info_result, []}},
- {options,
- [{ciphers,[CipherSuite]} |
- ClientOpts]}]),
-
- ClientMsg = {ok, {Version, CipherSuite}},
-
- Result = ssl_test_lib:wait_for_result(Client, ClientMsg),
+ {from, self()},
+ {mfa, {ssl_test_lib, cipher_result, [ConnectionInfo]}},
+ {options,
+ [{ciphers,[CipherSuite]} |
+ ClientOpts]}]),
+
+ port_command(OpenSslPort, "Hello\n"),
+
+ receive
+ {Port, {data, _}} when is_port(Port) ->
+ ok
+ after 500 ->
+ test_server:format("Time out on openssl port, check that"
+ " the messages Hello and world are received"
+ " during close of port" , []),
+ ok
+ end,
+
+ port_command(OpenSslPort, " world\n"),
+
+ Result = ssl_test_lib:wait_for_result(Client, ok),
close_port(OpenSslPort),
%% Clean close down!
diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk
index 254ee8b986..30a0a3b3f7 100644
--- a/lib/ssl/vsn.mk
+++ b/lib/ssl/vsn.mk
@@ -1,63 +1,2 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1999-2010. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-#
-SSL_VSN = 4.0.1
-
-TICKETS = OTP-8721
-
-#TICKETS_4.0 = OTP-8587\
-# OTP-8695
-
-#TICKETS_3.11.1 = OTP-8679 \
-# OTP-7047 \
-# OTP-7049 \
-# OTP-8568 \
-# OTP-8588
-
-#TICKETS_3.11 = OTP-8517 \
-# OTP-7046 \
-# OTP-8557 \
-# OTP-8560 \
-# OTP-8545 \
-# OTP-8554
-
-#TICKETS_3.10.9 = OTP-8510
-
-#TICKETS_3.10.8 = OTP-8372 OTP-8441 OTP-8459
-#TICKETS_3.10.7 = OTP-8260 OTP-8218 OTP-8250
-
-#TICKETS_3.10.6 = OTP-8275
-
-#TICKETS_3.10.5 = OTP-8224 OTP-8244
-
-#TICKETS_3.10.4 = OTP-8137
-
-#TICKETS_3.10.3 = OTP-8011
-#TICKETS_3.10.2 = OTP-7963
-
-# TICKETS_3.10.1 = OTP-7878 \
-# OTP-7656 \
-# OTP-7870 \
-# OTP-7871
-
-# TICKETS_3.10 = OTP-7258 \
-# OTP-6894 \
-# OTP-7037 \
-# OTP-7039 \
-# OTP-7150
+SSL_VSN = 4.1
diff --git a/lib/stdlib/doc/src/dets.xml b/lib/stdlib/doc/src/dets.xml
index 8d1398d3b7..ad100d2cf5 100644
--- a/lib/stdlib/doc/src/dets.xml
+++ b/lib/stdlib/doc/src/dets.xml
@@ -109,7 +109,7 @@ bool() = true | false
file() = string()
int() = integer() >= 0
keypos() = integer() >= 1
-name() = atom() | ref()
+name() = atom() | reference()
no_slots() = integer() >= 0 | default
object() = tuple()
object_cont() = tuple()
@@ -759,7 +759,7 @@ ok
<fsummary>Open an existing Dets table.</fsummary>
<type>
<v>FileName = file()</v>
- <v>Reference = ref()</v>
+ <v>Reference = reference()</v>
</type>
<desc>
<p>Opens an existing table. If the table has not been properly
diff --git a/lib/stdlib/doc/src/erl_id_trans.xml b/lib/stdlib/doc/src/erl_id_trans.xml
index 7c821d2efc..cfb18ec131 100644
--- a/lib/stdlib/doc/src/erl_id_trans.xml
+++ b/lib/stdlib/doc/src/erl_id_trans.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>1996</year>
- <year>2007</year>
+ <year>2010</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -70,7 +70,8 @@
<section>
<title>See Also</title>
- <p><seealso marker="erl_parse">erl_parse(3)</seealso>, compile(3).</p>
+ <p><seealso marker="erl_parse">erl_parse(3)</seealso>,
+ <seealso marker="compiler:compile">compile(3)</seealso>.</p>
</section>
</erlref>
diff --git a/lib/stdlib/doc/src/erl_lint.xml b/lib/stdlib/doc/src/erl_lint.xml
index 6a7d37765c..8639d678fa 100644
--- a/lib/stdlib/doc/src/erl_lint.xml
+++ b/lib/stdlib/doc/src/erl_lint.xml
@@ -96,8 +96,8 @@
<p>The <c>AbsForms</c> of a module which comes from a file
that is read through <c>epp</c>, the Erlang pre-processor,
can come from many files. This means that any references to
- errors must include the file name (see <seealso marker="epp">epp(3)</seealso>, or parser <seealso marker="erl_parse">erl_parse(3)</seealso> The warnings and
- errors returned have the following format:
+ errors must include the file name (see <seealso marker="epp">epp(3)</seealso>, or parser <seealso marker="erl_parse">erl_parse(3)</seealso>).
+ The warnings and errors returned have the following format:
</p>
<code type="none">
[{FileName2,[ErrorInfo]}] </code>
diff --git a/lib/stdlib/doc/src/erl_parse.xml b/lib/stdlib/doc/src/erl_parse.xml
index ae8a8afd5c..18b592deea 100644
--- a/lib/stdlib/doc/src/erl_parse.xml
+++ b/lib/stdlib/doc/src/erl_parse.xml
@@ -39,7 +39,7 @@
expressions, or terms. The Abstract Format is described in the ERTS
User's Guide.
Note that a token list must end with the <em>dot</em> token in order
- to be acceptable to the parse functions (see erl_scan).</p>
+ to be acceptable to the parse functions (see <seealso marker="erl_scan">erl_scan(3)</seealso>).</p>
</description>
<funcs>
<func>
diff --git a/lib/stdlib/doc/src/ets.xml b/lib/stdlib/doc/src/ets.xml
index 5df60a92e5..702e1b928e 100644
--- a/lib/stdlib/doc/src/ets.xml
+++ b/lib/stdlib/doc/src/ets.xml
@@ -56,8 +56,8 @@
Even if there are no references to a table from any process, it
will not automatically be destroyed unless the owner process
terminates. It can be destroyed explicitly by using
- <c>delete/1</c>.</p>
- <p>Since R13B01, table ownership can be transferred at process termination
+ <c>delete/1</c>. The default owner is the process that created the
+ table. Table ownership can be transferred at process termination
by using the <seealso marker="#heir">heir</seealso> option or explicitly
by calling <seealso marker="#give_away/3">give_away/3</seealso>.</p>
<p>Some implementation details:</p>
@@ -82,11 +82,15 @@
<c>float()</c> that extends to the same value, hence the key
<c>1</c> and the key <c>1.0</c> are regarded as equal in an
<c>ordered_set</c> table.</p>
- <p>In general, the functions below will exit with reason
- <c>badarg</c> if any argument is of the wrong format, or if the
- table identifier is invalid.</p>
</description>
-
+ <section>
+ <title>Failure</title>
+ <p>In general, the functions below will exit with reason
+ <c>badarg</c> if any argument is of the wrong format, if the
+ table identifier is invalid or if the operation is denied due to
+ table access rights (<seealso marker="#protected">protected</seealso>
+ or <seealso marker="#private">private</seealso>).</p>
+ </section>
<section><marker id="concurrency"></marker>
<title>Concurrency</title>
<p>This module provides some limited support for concurrent access.
@@ -947,7 +951,7 @@ ets:select(Table,MatchSpec),</code>
<type>
<v>Name = atom()</v>
<v>Options = [Option]</v>
- <v>&nbsp;Option = Type | Access | named_table | {keypos,Pos} | {heir,pid(),HeirData} | {heir,none} | {write_concurrency,bool()}</v>
+ <v>&nbsp;Option = Type | Access | named_table | {keypos,Pos} | {heir,pid(),HeirData} | {heir,none} | {write_concurrency,bool()} | {read_concurrency,bool()}</v>
<v>&nbsp;&nbsp;Type = set | ordered_set | bag | duplicate_bag</v>
<v>&nbsp;&nbsp;Access = public | protected | private</v>
<v>&nbsp;&nbsp;Pos = int()</v>
@@ -963,7 +967,7 @@ ets:select(Table,MatchSpec),</code>
table is named or not. If one or more options are left out,
the default values are used. This means that not specifying
any options (<c>[]</c>) is the same as specifying
- <c>[set,protected,{keypos,1},{heir,none},{write_concurrency,false}]</c>.</p>
+ <c>[set,protected,{keypos,1},{heir,none},{write_concurrency,false},{read_concurrency,false}]</c>.</p>
<list type="bulleted">
<item>
<p><c>set</c>
@@ -1002,12 +1006,14 @@ ets:select(Table,MatchSpec),</code>
Any process may read or write to the table.</p>
</item>
<item>
+ <marker id="protected"></marker>
<p><c>protected</c>
The owner process can read and write to the table. Other
processes can only read the table. This is the default
setting for the access rights.</p>
</item>
<item>
+ <marker id="private"></marker>
<p><c>private</c>
Only the owner process can read or write to the table.</p>
</item>
@@ -1385,6 +1391,28 @@ is_integer(X), is_integer(Y), X + Y < 4711]]></code>
</desc>
</func>
<func>
+ <name>select_count(Tab, MatchSpec) -> NumMatched</name>
+ <fsummary>Match the objects in an ETS table against a match_spec and returns the number of objects for which the match_spec returned 'true'</fsummary>
+ <type>
+ <v>Tab = tid() | atom()</v>
+ <v>Object = tuple()</v>
+ <v>MatchSpec = match_spec()</v>
+ <v>NumMatched = integer()</v>
+ </type>
+ <desc>
+ <p>Matches the objects in the table <c>Tab</c> using a
+ <seealso marker="#match_spec">match_spec</seealso>. If the
+ match_spec returns <c>true</c> for an object, that object
+ considered a match and is counted. For any other result from
+ the match_spec the object is not considered a match and is
+ therefore not counted.</p>
+ <p>The function could be described as a <c>match_delete/2</c>
+ that does not actually delete any elements, but only counts
+ them.</p>
+ <p>The function returns the number of objects matched.</p>
+ </desc>
+ </func>
+ <func>
<name>select_delete(Tab, MatchSpec) -> NumDeleted</name>
<fsummary>Match the objects in an ETS table against a match_spec and deletes objects where the match_spec returns 'true'</fsummary>
<type>
@@ -1411,25 +1439,82 @@ is_integer(X), is_integer(Y), X + Y < 4711]]></code>
</desc>
</func>
<func>
- <name>select_count(Tab, MatchSpec) -> NumMatched</name>
- <fsummary>Match the objects in an ETS table against a match_spec and returns the number of objects for which the match_spec returned 'true'</fsummary>
+ <name>select_reverse(Tab, MatchSpec) -> [Match]</name>
+ <fsummary>Match the objects in an ETS table against a match_spec.</fsummary>
<type>
<v>Tab = tid() | atom()</v>
- <v>Object = tuple()</v>
+ <v>Match = term()</v>
<v>MatchSpec = match_spec()</v>
- <v>NumMatched = integer()</v>
</type>
<desc>
- <p>Matches the objects in the table <c>Tab</c> using a
- <seealso marker="#match_spec">match_spec</seealso>. If the
- match_spec returns <c>true</c> for an object, that object
- considered a match and is counted. For any other result from
- the match_spec the object is not considered a match and is
- therefore not counted.</p>
- <p>The function could be described as a <c>match_delete/2</c>
- that does not actually delete any elements, but only counts
- them.</p>
- <p>The function returns the number of objects matched.</p>
+
+ <p>Works like <c>select/2</c>, but returns the list in reverse
+ order for the <c>ordered_set</c> table type. For all other table
+ types, the return value is identical to that of <c>select/2</c>.</p>
+
+ </desc>
+ </func>
+ <func>
+ <name>select_reverse(Tab, MatchSpec, Limit) -> {[Match],Continuation} | '$end_of_table'</name>
+ <fsummary>Match the objects in an ETS table against a match_spec and returns part of the answers.</fsummary>
+ <type>
+ <v>Tab = tid() | atom()</v>
+ <v>Match = term()</v>
+ <v>MatchSpec = match_spec()</v>
+ <v>Continuation = term()</v>
+ </type>
+ <desc>
+
+ <p>Works like <c>select/3</c>, but for the <c>ordered_set</c>
+ table type, traversing is done starting at the last object in
+ Erlang term order and moves towards the first. For all other
+ table types, the return value is identical to that of
+ <c>select/3</c>.</p>
+
+ <p>Note that this is <em>not</em> equivalent to
+ reversing the result list of a <c>select/3</c> call, as the result list
+ is not only reversed, but also contains the last <c>Limit</c>
+ matching objects in the table, not the first.</p>
+
+ </desc>
+ </func>
+ <func>
+ <name>select_reverse(Continuation) -> {[Match],Continuation} | '$end_of_table'</name>
+ <fsummary>Continue matching objects in an ETS table.</fsummary>
+ <type>
+ <v>Match = term()</v>
+ <v>Continuation = term()</v>
+ </type>
+ <desc>
+
+ <p>Continues a match started with
+ <c>ets:select_reverse/3</c>. If the table is an
+ <c>ordered_set</c>, the traversal of the table will continue
+ towards objects with keys earlier in the Erlang term order. The
+ returned list will also contain objects with keys in reverse
+ order.</p>
+
+ <p>For all other table types, the behaviour is exatly that of <c>select/1</c>.</p>
+ <p>Example:</p>
+ <code>
+1> T = ets:new(x,[ordered_set]).
+2> [ ets:insert(T,{N}) || N &lt;- lists:seq(1,10) ].
+...
+3> {R0,C0} = ets:select_reverse(T,[{'_',[],['$_']}],4).
+...
+4> R0.
+[{10},{9},{8},{7}]
+5> {R1,C1} = ets:select_reverse(C0).
+...
+6> R1.
+[{6},{5},{4},{3}]
+7> {R2,C2} = ets:select_reverse(C1).
+...
+8> R2.
+[{2},{1}]
+9> '$end_of_table' = ets:select_reverse(C2).
+...
+ </code>
</desc>
</func>
<func>
diff --git a/lib/stdlib/doc/src/filelib.xml b/lib/stdlib/doc/src/filelib.xml
index c1c4ca9350..4ff3b22f32 100644
--- a/lib/stdlib/doc/src/filelib.xml
+++ b/lib/stdlib/doc/src/filelib.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2003</year><year>2009</year>
+ <year>2003</year><year>2010</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -160,6 +160,12 @@ DeepList = [char() | atom() | DeepList]</code>
<p>Matches any number of characters up to the end of
the filename, the next dot, or the next slash.</p>
</item>
+ <tag>[Character1,Character2,...]</tag>
+ <item>
+ <p>Matches any of the characters listed. Two characters
+ separated by a hyphen will match a range of characters.
+ Example: <c>[A-Z]</c> will match any uppercase letter.</p>
+ </item>
<tag>{Item,...}</tag>
<item>
<p>Alternation. Matches one of the alternatives.</p>
diff --git a/lib/stdlib/doc/src/io_protocol.xml b/lib/stdlib/doc/src/io_protocol.xml
index b52e862a5c..a97d996d98 100644
--- a/lib/stdlib/doc/src/io_protocol.xml
+++ b/lib/stdlib/doc/src/io_protocol.xml
@@ -79,7 +79,7 @@ sends the reply to.</item>
io_reply. The io-module in the Erlang standard library simply uses the pid()
of the io_server as the ReplyAs datum, but a more complicated client
could have several outstanding io-requests to the same server and
-would then use i.e. a ref() or something else to differentiate among
+would then use i.e. a reference() or something else to differentiate among
the incoming io_reply's. The ReplyAs element should be considered
opaque by the io_server. Note that the pid() of the server is not
explicitly present in the io_reply. The reply can be sent from any
diff --git a/lib/stdlib/doc/src/lists.xml b/lib/stdlib/doc/src/lists.xml
index b3ad7aaf46..92c4eb4f4c 100644
--- a/lib/stdlib/doc/src/lists.xml
+++ b/lib/stdlib/doc/src/lists.xml
@@ -220,7 +220,7 @@
follows:</p>
<code type="none">
flatmap(Fun, List1) ->
- append(map(Fun, List1))</code>
+ append(map(Fun, List1)).</code>
<p>Example:</p>
<pre>
> <input>lists:flatmap(fun(X)->[X,X] end, [a,b,c]).</input>
@@ -523,7 +523,7 @@ flatmap(Fun, List1) ->
<v>&nbsp;A = B = term()</v>
</type>
<desc>
- <p><c>mapfold</c> combines the operations of <c>map/2</c> and
+ <p><c>mapfoldl</c> combines the operations of <c>map/2</c> and
<c>foldl/3</c> into one pass. An example, summing
the elements in a list and double them at the same time:</p>
<pre>
@@ -543,7 +543,7 @@ flatmap(Fun, List1) ->
<v>&nbsp;A = B = term()</v>
</type>
<desc>
- <p><c>mapfold</c> combines the operations of <c>map/2</c> and
+ <p><c>mapfoldr</c> combines the operations of <c>map/2</c> and
<c>foldr/3</c> into one pass.</p>
</desc>
</func>
diff --git a/lib/stdlib/doc/src/notes.xml b/lib/stdlib/doc/src/notes.xml
index 23d1e8b7de..6c618bc798 100644
--- a/lib/stdlib/doc/src/notes.xml
+++ b/lib/stdlib/doc/src/notes.xml
@@ -30,6 +30,142 @@
</header>
<p>This document describes the changes made to the STDLIB application.</p>
+<section><title>STDLIB 1.17.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>reference() has been substituted for ref() in the
+ documentation.</p>
+ <p>
+ Own Id: OTP-8733</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The ms_transform now warns if the fun head shadows
+ surrounding variables (just like the warnings you would
+ get for an ordinary fun in the same context).</p>
+ <p>
+ Own Id: OTP-6759</p>
+ </item>
+ <item>
+ <p>
+ ets:select_reverse/{1,2,3} are now documented.</p>
+ <p>
+ Own Id: OTP-7863</p>
+ </item>
+ <item>
+ <p>
+ Large parts of the <c>ethread</c> library have been
+ rewritten. The <c>ethread</c> library is an Erlang
+ runtime system internal, portable thread library used by
+ the runtime system itself.</p>
+ <p>
+ Most notable improvement is a reader optimized rwlock
+ implementation which dramatically improve the performance
+ of read-lock/read-unlock operations on multi processor
+ systems by avoiding ping-ponging of the rwlock cache
+ lines. The reader optimized rwlock implementation is used
+ by miscellaneous rwlocks in the runtime system that are
+ known to be read-locked frequently, and can be enabled on
+ ETS tables by passing the <seealso
+ marker="stdlib:ets#new_2_read_concurrency">{read_concurrency,
+ true}</seealso> option upon table creation. See the
+ documentation of <seealso
+ marker="stdlib:ets#new/2">ets:new/2</seealso> for more
+ information. The reader optimized rwlock implementation
+ can be fine tuned when starting the runtime system. For
+ more information, see the documentation of the <seealso
+ marker="erts:erl#+rg">+rg</seealso> command line argument
+ of <c>erl</c>.</p>
+ <p>
+ There is also a new implementation of rwlocks that is not
+ optimized for readers. Both implementations interleaves
+ readers and writers during contention as opposed to,
+ e.g., the NPTL (Linux) pthread rwlock implementation
+ which use either a reader or writer preferred strategy.
+ The reader/writer preferred strategy is problematic since
+ it starves threads doing the non-preferred operation.</p>
+ <p>
+ The new rwlock implementations in general performs better
+ in ERTS than common pthread implementations. However, in
+ some extremely heavily contended cases this is not the
+ case. Such heavy contention can more or less only appear
+ on ETS tables. This when multiple processes do very large
+ amounts of write locked operations simultaneously on the
+ same table. Such use of ETS is bad regardless of rwlock
+ implementation, will never scale, and is something we
+ strongly advise against.</p>
+ <p>
+ The new rwlock implementations depend on atomic
+ operations. If no native atomic implementation is found,
+ a fallback solution will be used. Using the fallback
+ implies a performance degradation. That is, it is more
+ important now than before to build OTP with a native
+ atomic implementation.</p>
+ <p>
+ The <c>ethread</c> library contains native atomic
+ implementations for, x86 (32 and 64 bit), powerpc (32
+ bit), sparc V9 (32 and 64 bit), and tilera (32 bit). On
+ other hardware gcc's builtin support for atomic memory
+ access will be used if such exists. If no such support is
+ found, <c>configure</c> will warn about no atomic
+ implementation available.</p>
+ <p>
+ The <c>ethread</c> library can now also use the
+ <c>libatomic_ops</c> library for atomic memory accesses.
+ This makes it possible for the Erlang runtime system to
+ utilize optimized native atomic operations on more
+ platforms than before. If <c>configure</c> warns about no
+ atomic implementation available, try using the
+ <c>libatomic_ops</c> library. Use the <seealso
+ marker="doc/installation_guide:INSTALL#How-to-Build-and-Install-ErlangOTP_A-Closer-Look-at-the-individual-Steps_Configuring">--with-libatomic_ops=PATH</seealso>
+ <c>configure</c> command line argument when specifying
+ where the <c>libatomic_ops</c> installation is located.
+ The <c>libatomic_ops</c> library can be downloaded from:
+ <url
+ href="http://www.hpl.hp.com/research/linux/atomic_ops/">http://www.hpl.hp.com/research/linux/atomic_ops/</url></p>
+ <p>
+ The changed API of the <c>ethread</c> library has also
+ caused modifications in the Erlang runtime system.
+ Preparations for the to come "delayed deallocation"
+ feature has also been done since it depends on the
+ <c>ethread</c> library.</p>
+ <p>
+ <em>Note</em>: When building for x86, the <c>ethread</c>
+ library will now use instructions that first appeared on
+ the pentium 4 processor. If you want the runtime system
+ to be compatible with older processors (back to 486) you
+ need to pass the <seealso
+ marker="doc/installation_guide:INSTALL#How-to-Build-and-Install-ErlangOTP_A-Closer-Look-at-the-individual-Steps_Configuring">--enable-ethread-pre-pentium4-compatibility</seealso>
+ <c>configure</c> command line argument when configuring
+ the system.</p>
+ <p>
+ Own Id: OTP-8544</p>
+ </item>
+ <item>
+ <p>
+ Some Built In Functions (BIFs) from the module erlang was
+ never made autoimported for backward compatibility
+ reasons. As local functions now override autoimports, new
+ autoimports is no longer a problem, why the following
+ BIFs are finally made autoimported: monitor/2, monitor/3,
+ demonitor/2, demonitor/3, error/1, error/2,
+ integer_to_list/2, list_to_integer/2.</p>
+ <p>
+ Own Id: OTP-8763</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>STDLIB 1.17</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/stdlib/doc/src/supervisor.xml b/lib/stdlib/doc/src/supervisor.xml
index c696434d49..45fa0847a8 100644
--- a/lib/stdlib/doc/src/supervisor.xml
+++ b/lib/stdlib/doc/src/supervisor.xml
@@ -156,7 +156,7 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules}
the child process to terminate by calling
<c>exit(Child,shutdown)</c> and then wait for an exit signal
with reason <c>shutdown</c> back from the child process. If
- no exit signal is received within the specified time,
+ no exit signal is received within the specified number of milliseconds,
the child process is unconditionally terminated using
<c>exit(Child,kill)</c>.</p>
<p>If the child process is another supervisor, <c>Shutdown</c>
diff --git a/lib/stdlib/doc/src/sys.xml b/lib/stdlib/doc/src/sys.xml
index 10ead62073..8cbfb9387b 100644
--- a/lib/stdlib/doc/src/sys.xml
+++ b/lib/stdlib/doc/src/sys.xml
@@ -34,7 +34,7 @@
<module>sys</module>
<modulesummary>A Functional Interface to System Messages</modulesummary>
<description>
- <p>This module contains functions for sending system messages used by programs, and messaged used for debugging purposes.
+ <p>This module contains functions for sending system messages used by programs, and messages used for debugging purposes.
</p>
<p>Functions used for implementation of processes
should also understand system messages such as debugging
diff --git a/lib/stdlib/src/beam_lib.erl b/lib/stdlib/src/beam_lib.erl
index e612bf71e7..74d4ad3da7 100644
--- a/lib/stdlib/src/beam_lib.erl
+++ b/lib/stdlib/src/beam_lib.erl
@@ -19,6 +19,10 @@
-module(beam_lib).
-behaviour(gen_server).
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
+%% Avoid warning for local function error/2 clashing with autoimported BIF.
+-compile({no_auto_import,[error/2]}).
-export([info/1,
cmp/2,
cmp_dirs/2,
diff --git a/lib/stdlib/src/c.erl b/lib/stdlib/src/c.erl
index e05a1c787f..6d50a575eb 100644
--- a/lib/stdlib/src/c.erl
+++ b/lib/stdlib/src/c.erl
@@ -20,6 +20,8 @@
%% Utilities to use from shell.
+%% Avoid warning for local function error/2 clashing with autoimported BIF.
+-compile({no_auto_import,[error/2]}).
-export([help/0,lc/1,c/1,c/2,nc/1,nc/2, nl/1,l/1,i/0,i/1,ni/0,
y/1, y/2,
lc_batch/0, lc_batch/1,
diff --git a/lib/stdlib/src/dets.erl b/lib/stdlib/src/dets.erl
index 4584b8184f..6c91f1efb7 100644
--- a/lib/stdlib/src/dets.erl
+++ b/lib/stdlib/src/dets.erl
@@ -147,6 +147,7 @@
bin, % small chunk not consumed, or 'eof' at end-of-file
alloc, % the part of the file not yet scanned, mostly a binary
tab,
+ proc, % the pid of the Dets process
match_program % true | compiled_match_spec() | undefined
}).
@@ -208,8 +209,6 @@ all() ->
bchunk(Tab, start) ->
badarg(treq(Tab, {bchunk_init, Tab}), [Tab, start]);
-bchunk(Tab, #dets_cont{bin = eof, tab = Tab}) ->
- '$end_of_table';
bchunk(Tab, #dets_cont{what = bchunk, tab = Tab} = State) ->
badarg(treq(Tab, {bchunk, State}), [Tab, State]);
bchunk(Tab, Term) ->
@@ -722,11 +721,14 @@ init_chunk_match(Tab, Pat, What, N) when is_integer(N), N >= 0;
N =:= default ->
case compile_match_spec(What, Pat) of
{Spec, MP} ->
- case req(dets_server:get_pid(Tab), {match, MP, Spec, N}) of
+ Proc = dets_server:get_pid(Tab),
+ case req(Proc, {match, MP, Spec, N}) of
{done, L} ->
- {L, #dets_cont{tab = Tab, what = What, bin = eof}};
+ {L, #dets_cont{tab = Tab, proc = Proc, what = What,
+ bin = eof}};
{cont, State} ->
- chunk_match(State#dets_cont{what = What, tab = Tab});
+ chunk_match(State#dets_cont{what = What, tab = Tab,
+ proc = Proc});
Error ->
Error
end;
@@ -736,34 +738,28 @@ init_chunk_match(Tab, Pat, What, N) when is_integer(N), N >= 0;
init_chunk_match(_Tab, _Pat, _What, _) ->
badarg.
-chunk_match(State) ->
- case catch dets_server:get_pid(State#dets_cont.tab) of
- {'EXIT', _Reason} ->
- badarg;
- _Proc when State#dets_cont.bin =:= eof ->
- '$end_of_table';
- Proc ->
- case req(Proc, {match_init, State}) of
- {cont, {Bins, NewState}} ->
- MP = NewState#dets_cont.match_program,
- case catch do_foldl_bins(Bins, MP) of
- {'EXIT', _} ->
- case ets:is_compiled_ms(MP) of
- true ->
- Bad = dets_utils:bad_object(chunk_match,
- Bins),
- req(Proc, {corrupt, Bad});
- false ->
- badarg
- end;
- [] ->
- chunk_match(NewState);
- Terms ->
- {Terms, NewState}
- end;
- Error ->
- Error
- end
+chunk_match(#dets_cont{proc = Proc}=State) ->
+ case req(Proc, {match_init, State}) of
+ '$end_of_table'=Reply ->
+ Reply;
+ {cont, {Bins, NewState}} ->
+ MP = NewState#dets_cont.match_program,
+ case catch do_foldl_bins(Bins, MP) of
+ {'EXIT', _} ->
+ case ets:is_compiled_ms(MP) of
+ true ->
+ Bad = dets_utils:bad_object(chunk_match, Bins),
+ req(Proc, {corrupt, Bad});
+ false ->
+ badarg
+ end;
+ [] ->
+ chunk_match(NewState);
+ Terms ->
+ {Terms, NewState}
+ end;
+ Error ->
+ Error
end.
do_foldl_bins(Bins, true) ->
@@ -1094,7 +1090,9 @@ do_apply_op(Op, From, Head, N) ->
{N2, H2} when is_record(H2, head), is_integer(N2) ->
open_file_loop(H2, N2);
H2 when is_record(H2, head) ->
- open_file_loop(H2, N)
+ open_file_loop(H2, N);
+ {{more,From1,Op1,N1}, NewHead} ->
+ do_apply_op(Op1, From1, NewHead, N1)
catch
exit:normal ->
exit(normal);
@@ -1363,37 +1361,35 @@ start_auto_save_timer(Head) ->
%% lookup requests in parallel. Evalute delete_object, delete and
%% insert as well.
stream_op(Op, Pid, Pids, Head, N) ->
- stream_op(Head, Pids, [], N, Pid, Op, Head#head.fixed).
+ #head{fixed = Fxd, update_mode = M} = Head,
+ stream_op(Head, Pids, [], N, Pid, Op, Fxd, M).
-stream_loop(Head, Pids, C, N, false = Fxd) ->
+stream_loop(Head, Pids, C, N, false = Fxd, M) ->
receive
?DETS_CALL(From, Message) ->
- stream_op(Head, Pids, C, N, From, Message, Fxd)
+ stream_op(Head, Pids, C, N, From, Message, Fxd, M)
after 0 ->
stream_end(Head, Pids, C, N, no_more)
end;
-stream_loop(Head, Pids, C, N, _Fxd) ->
+stream_loop(Head, Pids, C, N, _Fxd, _M) ->
stream_end(Head, Pids, C, N, no_more).
-stream_op(Head, Pids, C, N, Pid, {lookup_keys,Keys}, Fxd) ->
+stream_op(Head, Pids, C, N, Pid, {lookup_keys,Keys}, Fxd, M) ->
NC = [{{lookup,Pid},Keys} | C],
- stream_loop(Head, Pids, NC, N, Fxd);
-stream_op(Head, Pids, C, N, Pid, {insert, _Objects} = Op, Fxd) ->
- NC = [Op | C],
- stream_loop(Head, [Pid | Pids], NC, N, Fxd);
-stream_op(Head, Pids, C, N, Pid, {insert_new, _Objects} = Op, Fxd) ->
+ stream_loop(Head, Pids, NC, N, Fxd, M);
+stream_op(Head, Pids, C, N, Pid, {insert, _Objects} = Op, Fxd, dirty = M) ->
NC = [Op | C],
- stream_loop(Head, [Pid | Pids], NC, N, Fxd);
-stream_op(Head, Pids, C, N, Pid, {delete_key, _Keys} = Op, Fxd) ->
+ stream_loop(Head, [Pid | Pids], NC, N, Fxd, M);
+stream_op(Head, Pids, C, N, Pid, {delete_key, _Keys} = Op, Fxd, dirty = M) ->
NC = [Op | C],
- stream_loop(Head, [Pid | Pids], NC, N, Fxd);
-stream_op(Head, Pids, C, N, Pid, {delete_object, _Objects} = Op, Fxd) ->
+ stream_loop(Head, [Pid | Pids], NC, N, Fxd, M);
+stream_op(Head, Pids, C, N, Pid, {delete_object, _Os} = Op, Fxd, dirty = M) ->
NC = [Op | C],
- stream_loop(Head, [Pid | Pids], NC, N, Fxd);
-stream_op(Head, Pids, C, N, Pid, {member, Key}, Fxd) ->
+ stream_loop(Head, [Pid | Pids], NC, N, Fxd, M);
+stream_op(Head, Pids, C, N, Pid, {member, Key}, Fxd, M) ->
NC = [{{lookup,[Pid]},[Key]} | C],
- stream_loop(Head, Pids, NC, N, Fxd);
-stream_op(Head, Pids, C, N, Pid, Op, _Fxd) ->
+ stream_loop(Head, Pids, NC, N, Fxd, M);
+stream_op(Head, Pids, C, N, Pid, Op, _Fxd, _M) ->
stream_end(Head, Pids, C, N, {Pid,Op}).
stream_end(Head, Pids0, C, N, Next) ->
@@ -1438,7 +1434,7 @@ stream_end2([], Ps, no_more, N, C, Head, _Reply) ->
penalty(Head, Ps, C),
{N, Head};
stream_end2([], _Ps, {From, Op}, N, _C, Head, _Reply) ->
- apply_op(Op, From, Head, N).
+ {{more,From,Op,N},Head}.
penalty(H, _Ps, _C) when H#head.fixed =:= false ->
ok;
@@ -1578,13 +1574,18 @@ do_bchunk_init(Head, Tab) ->
L = dets_utils:all_allocated(H2),
C0 = #dets_cont{no_objs = default, bin = <<>>, alloc = L},
BinParms = term_to_binary(Parms),
- {H2, {C0#dets_cont{tab = Tab, what = bchunk}, [BinParms]}}
+ {H2, {C0#dets_cont{tab = Tab, proc = self(),what = bchunk},
+ [BinParms]}}
end;
{NewHead, _} = HeadError when is_record(NewHead, head) ->
HeadError
end.
%% -> {NewHead, {cont(), [binary()]}} | {NewHead, Error}
+do_bchunk(Head, #dets_cont{proc = Proc}) when Proc =/= self() ->
+ {Head, badarg};
+do_bchunk(Head, #dets_cont{bin = eof}) ->
+ {Head, '$end_of_table'};
do_bchunk(Head, State) ->
case dets_v9:read_bchunks(Head, State#dets_cont.alloc) of
{error, Reason} ->
@@ -1954,6 +1955,8 @@ flookup_keys(Head, Keys) ->
end.
%% -> {NewHead, Result}
+fmatch_init(Head, #dets_cont{bin = eof}) ->
+ {Head, '$end_of_table'};
fmatch_init(Head, C) ->
case scan(Head, C) of
{scan_error, Reason} ->
diff --git a/lib/stdlib/src/dets_v8.erl b/lib/stdlib/src/dets_v8.erl
index 1f9f84cd27..af36958c1c 100644
--- a/lib/stdlib/src/dets_v8.erl
+++ b/lib/stdlib/src/dets_v8.erl
@@ -1074,6 +1074,8 @@ wl([], _Type, Del, Lookup, I, Objs) ->
[{Del, Lookup, Objs} | I].
%% -> {NewHead, ok} | {NewHead, Error}
+may_grow(Head, 0, once) ->
+ {Head, ok};
may_grow(Head, _N, _How) when Head#head.fixed =/= false ->
{Head, ok};
may_grow(#head{access = read}=Head, _N, _How) ->
diff --git a/lib/stdlib/src/dets_v9.erl b/lib/stdlib/src/dets_v9.erl
index 53238e962f..132af01f79 100644
--- a/lib/stdlib/src/dets_v9.erl
+++ b/lib/stdlib/src/dets_v9.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1908,6 +1908,9 @@ write_cache(Head) ->
end.
%% -> {NewHead, ok} | {NewHead, Error}
+may_grow(Head, 0, once) ->
+ %% Do not re-hash if there is a chance that the file is not dirty.
+ {Head, ok};
may_grow(Head, _N, _How) when Head#head.fixed =/= false ->
{Head, ok};
may_grow(#head{access = read}=Head, _N, _How) ->
diff --git a/lib/stdlib/src/digraph.erl b/lib/stdlib/src/digraph.erl
index b5f52da921..5edc868a94 100644
--- a/lib/stdlib/src/digraph.erl
+++ b/lib/stdlib/src/digraph.erl
@@ -36,7 +36,7 @@
-export([get_short_path/3, get_short_cycle/2]).
--export_type([d_type/0, vertex/0]).
+-export_type([digraph/0, d_type/0, vertex/0]).
-record(digraph, {vtab = notable :: ets:tab(),
etab = notable :: ets:tab(),
diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl
index 81b2431f40..e5ccaddbb4 100644
--- a/lib/stdlib/src/epp.erl
+++ b/lib/stdlib/src/epp.erl
@@ -33,7 +33,9 @@
%% Epp state record.
-record(epp, {file, %Current file
location, %Current location
+ delta, %Offset from Location (-file)
name="", %Current file name
+ name2="", %-"-, modified by -file
istk=[], %Ifdef stack
sstk=[], %State stack
path=[], %Include-path
@@ -234,8 +236,8 @@ init_server(Pid, Name, File, AtLocation, Path, Pdm, Pre) ->
case user_predef(Pdm, Ms0) of
{ok,Ms1} ->
epp_reply(Pid, {ok,self()}),
- St = #epp{file=File, location=AtLocation, name=Name,
- path=Path, macs=Ms1, pre_opened = Pre},
+ St = #epp{file=File, location=AtLocation, delta=0, name=Name,
+ name2=Name, path=Path, macs=Ms1, pre_opened = Pre},
From = wait_request(St),
enter_file_reply(From, Name, AtLocation, AtLocation),
wait_req_scan(St);
@@ -358,8 +360,8 @@ enter_file2(NewF, Pname, From, St, AtLocation, ExtraPath) ->
enter_file_reply(From, Pname, Loc, AtLocation),
Ms = dict:store({atom,'FILE'}, {none,[{string,Loc,Pname}]}, St#epp.macs),
Path = St#epp.path ++ ExtraPath,
- #epp{location=Loc,file=NewF,
- name=Pname,sstk=[St|St#epp.sstk],path=Path,macs=Ms}.
+ #epp{file=NewF,location=Loc,name=Pname,delta=0,
+ sstk=[St|St#epp.sstk],path=Path,macs=Ms}.
enter_file_reply(From, Name, Location, AtLocation) ->
Attr = loc_attr(AtLocation),
@@ -391,14 +393,23 @@ leave_file(From, St) ->
case St#epp.sstk of
[OldSt|Sts] ->
close_file(St),
- enter_file_reply(From, OldSt#epp.name,
- OldSt#epp.location, OldSt#epp.location),
+ #epp{location=OldLoc, delta=Delta, name=OldName,
+ name2=OldName2} = OldSt,
+ CurrLoc = add_line(OldLoc, Delta),
Ms = dict:store({atom,'FILE'},
- {none,
- [{string,OldSt#epp.location,
- OldSt#epp.name}]},
+ {none,[{string,CurrLoc,OldName2}]},
St#epp.macs),
- wait_req_scan(OldSt#epp{sstk=Sts,macs=Ms});
+ NextSt = OldSt#epp{sstk=Sts,macs=Ms},
+ enter_file_reply(From, OldName, CurrLoc, CurrLoc),
+ case OldName2 =:= OldName of
+ true ->
+ From;
+ false ->
+ NFrom = wait_request(NextSt),
+ enter_file_reply(NFrom, OldName2, OldLoc,
+ neg_line(CurrLoc))
+ end,
+ wait_req_scan(NextSt);
[] ->
epp_reply(From, {eof,St#epp.location}),
wait_req_scan(St)
@@ -768,7 +779,8 @@ scan_file([{'(',_Llp},{string,_Ls,Name},{',',_Lc},{integer,_Li,Ln},{')',_Lrp},
Ms = dict:store({atom,'FILE'}, {none,[{string,1,Name}]}, St#epp.macs),
Locf = loc(Tf),
NewLoc = new_location(Ln, St#epp.location, Locf),
- wait_req_scan(St#epp{name=Name,location=NewLoc,macs=Ms});
+ Delta = abs(get_line(element(2, Tf)))-Ln + St#epp.delta,
+ wait_req_scan(St#epp{name2=Name,location=NewLoc,delta=Delta,macs=Ms});
scan_file(_Toks, Tf, From, St) ->
epp_reply(From, {error,{loc(Tf),epp,{bad,file}}}),
wait_req_scan(St).
@@ -1132,6 +1144,9 @@ neg_line(L) ->
abs_line(L) ->
erl_scan:set_attribute(line, L, fun(Line) -> abs(Line) end).
+add_line(L, Offset) ->
+ erl_scan:set_attribute(line, L, fun(Line) -> Line+Offset end).
+
start_loc(Line) when is_integer(Line) ->
1;
start_loc({_Line, _Column}) ->
@@ -1191,10 +1206,10 @@ interpret_file_attr([{attribute,Loc,file,{File,Line}}=Form | Forms],
%% -include or -include_lib
% true = L =:= Line,
case Fs of
- [_, Delta1, File | Fs1] -> % end of included file
- [Form | interpret_file_attr(Forms, Delta1, [File | Fs1])];
+ [_, File | Fs1] -> % end of included file
+ [Form | interpret_file_attr(Forms, 0, [File | Fs1])];
_ -> % start of included file
- [Form | interpret_file_attr(Forms, 0, [File, Delta | Fs])]
+ [Form | interpret_file_attr(Forms, 0, [File | Fs])]
end
end;
interpret_file_attr([Form0 | Forms], Delta, Fs) ->
diff --git a/lib/stdlib/src/erl_internal.erl b/lib/stdlib/src/erl_internal.erl
index bf6e5bc5ca..b30b02a96f 100644
--- a/lib/stdlib/src/erl_internal.erl
+++ b/lib/stdlib/src/erl_internal.erl
@@ -247,10 +247,14 @@ bif(check_process_code, 2) -> true;
bif(concat_binary, 1) -> true;
bif(date, 0) -> true;
bif(delete_module, 1) -> true;
+bif(demonitor, 1) -> true;
+bif(demonitor, 2) -> true;
bif(disconnect_node, 1) -> true;
bif(element, 2) -> true;
bif(erase, 0) -> true;
bif(erase, 1) -> true;
+bif(error, 1) -> true;
+bif(error, 2) -> true;
bif(exit, 1) -> true;
bif(exit, 2) -> true;
bif(float, 1) -> true;
@@ -266,6 +270,7 @@ bif(halt, 0) -> true;
bif(halt, 1) -> true;
bif(hd, 1) -> true;
bif(integer_to_list, 1) -> true;
+bif(integer_to_list, 2) -> true;
bif(iolist_size, 1) -> true;
bif(iolist_to_binary, 1) -> true;
bif(is_alive, 0) -> true;
@@ -295,6 +300,7 @@ bif(list_to_bitstring, 1) -> true;
bif(list_to_existing_atom, 1) -> true;
bif(list_to_float, 1) -> true;
bif(list_to_integer, 1) -> true;
+bif(list_to_integer, 2) -> true;
bif(list_to_pid, 1) -> true;
bif(list_to_tuple, 1) -> true;
bif(load_module, 2) -> true;
@@ -302,6 +308,8 @@ bif(make_ref, 0) -> true;
bif(max,2) -> true;
bif(min,2) -> true;
bif(module_loaded, 1) -> true;
+bif(monitor, 2) -> true;
+bif(monitor, 3) -> true;
bif(monitor_node, 2) -> true;
bif(node, 0) -> true;
bif(node, 1) -> true;
diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl
index 077621ac91..0c2d3db8ec 100644
--- a/lib/stdlib/src/erl_lint.erl
+++ b/lib/stdlib/src/erl_lint.erl
@@ -311,6 +311,8 @@ format_error({ill_defined_behaviour_callbacks,Behaviour}) ->
%% --- types and specs ---
format_error({singleton_typevar, Name}) ->
io_lib:format("type variable ~w is only used once (is unbound)", [Name]);
+format_error({bad_export_type, _ETs}) ->
+ io_lib:format("bad export_type declaration", []);
format_error({duplicated_export_type, {T, A}}) ->
io_lib:format("type ~w/~w already exported", [T, A]);
format_error({undefined_type, {TypeName, Arity}}) ->
@@ -1128,8 +1130,7 @@ export(Line, Es, #lint{exports = Es0, called = Called} = St0) ->
export_type(Line, ETs, #lint{usage = Usage, exp_types = ETs0} = St0) ->
UTs0 = Usage#usage.used_types,
- {ETs1,UTs1,St1} =
- foldl(fun (TA, {E,U,St2}) ->
+ try foldl(fun ({T,A}=TA, {E,U,St2}) when is_atom(T), is_integer(A) ->
St = case gb_sets:is_element(TA, E) of
true ->
Warn = {duplicated_export_type,TA},
@@ -1139,8 +1140,13 @@ export_type(Line, ETs, #lint{usage = Usage, exp_types = ETs0} = St0) ->
end,
{gb_sets:add_element(TA, E), dict:store(TA, Line, U), St}
end,
- {ETs0,UTs0,St0}, ETs),
- St1#lint{usage = Usage#usage{used_types = UTs1}, exp_types = ETs1}.
+ {ETs0,UTs0,St0}, ETs) of
+ {ETs1,UTs1,St1} ->
+ St1#lint{usage = Usage#usage{used_types = UTs1}, exp_types = ETs1}
+ catch
+ error:_ ->
+ add_error(Line, {bad_export_type, ETs}, St0)
+ end.
-type import() :: {module(), [fa()]} | module().
-spec import(line(), import(), lint_state()) -> lint_state().
diff --git a/lib/stdlib/src/eval_bits.erl b/lib/stdlib/src/eval_bits.erl
index 3671aecdcb..2cbd6cdae7 100644
--- a/lib/stdlib/src/eval_bits.erl
+++ b/lib/stdlib/src/eval_bits.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,6 +19,8 @@
%%
-module(eval_bits).
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([expr_grp/3,expr_grp/5,match_bits/6,
match_bits/7,bin_gen/6]).
diff --git a/lib/stdlib/src/file_sorter.erl b/lib/stdlib/src/file_sorter.erl
index 3875eca39d..2a5b08b581 100644
--- a/lib/stdlib/src/file_sorter.erl
+++ b/lib/stdlib/src/file_sorter.erl
@@ -18,6 +18,8 @@
%%
-module(file_sorter).
+%% Avoid warning for local function error/2 clashing with autoimported BIF.
+-compile({no_auto_import,[error/2]}).
-export([sort/1, sort/2, sort/3,
keysort/2, keysort/3, keysort/4,
merge/2, merge/3,
diff --git a/lib/stdlib/src/filelib.erl b/lib/stdlib/src/filelib.erl
index 5c5e084e17..d5ddf9ed7e 100644
--- a/lib/stdlib/src/filelib.erl
+++ b/lib/stdlib/src/filelib.erl
@@ -20,6 +20,8 @@
%% File utilities.
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([wildcard/1, wildcard/2, is_dir/1, is_file/1, is_regular/1,
compile_wildcard/1]).
-export([fold_files/5, last_modified/1, file_size/1, ensure_dir/1]).
diff --git a/lib/stdlib/src/gb_sets.erl b/lib/stdlib/src/gb_sets.erl
index 086dc79b46..113f29e252 100644
--- a/lib/stdlib/src/gb_sets.erl
+++ b/lib/stdlib/src/gb_sets.erl
@@ -657,7 +657,7 @@ intersection_2([], _, As, S) ->
intersection_2(_, [], As, S) ->
{S, balance_revlist(As, S)}.
--spec intersection([gb_set()]) -> gb_set().
+-spec intersection([gb_set(),...]) -> gb_set().
intersection([S | Ss]) ->
intersection_list(S, Ss).
diff --git a/lib/stdlib/src/lists.erl b/lib/stdlib/src/lists.erl
index 08ee595f4d..c669c1f7c1 100644
--- a/lib/stdlib/src/lists.erl
+++ b/lib/stdlib/src/lists.erl
@@ -350,7 +350,7 @@ sort_1(X, [], R) ->
%% merge(List) -> L
%% merges a list of sorted lists
--spec merge([T]) -> [T].
+-spec merge([[T]]) -> [T].
merge(L) ->
mergel(L, []).
@@ -358,7 +358,7 @@ merge(L) ->
%% merge3(X, Y, Z) -> L
%% merges three sorted lists X, Y and Z
--spec merge3([_], [_], [_]) -> [_].
+-spec merge3([X], [Y], [Z]) -> [(X | Y | Z)].
merge3(L1, [], L3) ->
merge(L1, L3);
@@ -370,7 +370,7 @@ merge3(L1, [H2 | T2], [H3 | T3]) ->
%% rmerge3(X, Y, Z) -> L
%% merges three reversed sorted lists X, Y and Z
--spec rmerge3([_], [_], [_]) -> [_].
+-spec rmerge3([X], [Y], [Z]) -> [(X | Y | Z)].
rmerge3(L1, [], L3) ->
rmerge(L1, L3);
@@ -382,7 +382,7 @@ rmerge3(L1, [H2 | T2], [H3 | T3]) ->
%% merge(X, Y) -> L
%% merges two sorted lists X and Y
--spec merge([_], [_]) -> [_].
+-spec merge([X], [Y]) -> [(X | Y)].
merge(T1, []) ->
T1;
@@ -394,7 +394,7 @@ merge(T1, [H2 | T2]) ->
%% reverse(rmerge(reverse(A),reverse(B))) is equal to merge(I,A,B).
--spec rmerge([_], [_]) -> [_].
+-spec rmerge([X], [Y]) -> [(X | Y)].
rmerge(T1, []) ->
T1;
@@ -420,12 +420,12 @@ thing_to_list(X) when is_list(X) -> X. %Assumed to be a string
%% flatten(List, Tail)
%% Flatten a list, adding optional tail.
--spec flatten([_]) -> [_].
+-spec flatten([term()]) -> [term()].
flatten(List) when is_list(List) ->
do_flatten(List, []).
--spec flatten([_], [_]) -> [_].
+-spec flatten([term()], [term()]) -> [term()].
flatten(List, Tail) when is_list(List), is_list(Tail) ->
do_flatten(List, Tail).
@@ -440,7 +440,7 @@ do_flatten([], Tail) ->
%% flatlength(List)
%% Calculate the length of a list of lists.
--spec flatlength([_]) -> non_neg_integer().
+-spec flatlength([term()]) -> non_neg_integer().
flatlength(List) ->
flatlength(List, 0).
@@ -481,7 +481,7 @@ flatlength([], L) -> L.
% keysearch3(Key, N, T);
%keysearch3(Key, N, []) -> false.
--spec keydelete(_, pos_integer(), [T]) -> [T].
+-spec keydelete(term(), pos_integer(), [T]) -> [T] when T :: tuple().
keydelete(K, N, L) when is_integer(N), N > 0 ->
keydelete3(K, N, L).
@@ -491,7 +491,7 @@ keydelete3(Key, N, [H|T]) ->
[H|keydelete3(Key, N, T)];
keydelete3(_, _, []) -> [].
--spec keyreplace(_, pos_integer(), [_], tuple()) -> [_].
+-spec keyreplace(term(), pos_integer(), [tuple()], tuple()) -> [tuple()].
keyreplace(K, N, L, New) when is_integer(N), N > 0, is_tuple(New) ->
keyreplace3(K, N, L, New).
@@ -502,7 +502,8 @@ keyreplace3(Key, Pos, [H|T], New) ->
[H|keyreplace3(Key, Pos, T, New)];
keyreplace3(_, _, [], _) -> [].
--spec keytake(_, pos_integer(), [_]) -> {'value', tuple(), [_]} | 'false'.
+-spec keytake(term(), pos_integer(), [tuple()]) ->
+ {'value', tuple(), [tuple()]} | 'false'.
keytake(Key, N, L) when is_integer(N), N > 0 ->
keytake(Key, N, L, []).
@@ -513,7 +514,8 @@ keytake(Key, N, [H|T], L) ->
keytake(Key, N, T, [H|L]);
keytake(_K, _N, [], _L) -> false.
--spec keystore(_, pos_integer(), [_], tuple()) -> [_].
+-spec keystore(term(), pos_integer(), [tuple()], tuple()) -> [tuple(),...].
+
keystore(K, N, L, New) when is_integer(N), N > 0, is_tuple(New) ->
keystore2(K, N, L, New).
@@ -524,7 +526,7 @@ keystore2(Key, N, [H|T], New) ->
keystore2(_Key, _N, [], New) ->
[New].
--spec keysort(pos_integer(), [T]) -> [T] when is_subtype(T, tuple()).
+-spec keysort(pos_integer(), [T]) -> [T] when T :: tuple().
keysort(I, L) when is_integer(I), I > 0 ->
case L of
@@ -582,7 +584,7 @@ keysort_1(_I, X, _EX, [], R) ->
lists:reverse(R, [X]).
-spec keymerge(pos_integer(), [X], [Y]) ->
- [R] when is_subtype(X, tuple()), is_subtype(Y, tuple()), is_subtype(R, tuple()).
+ [R] when X :: tuple(), Y :: tuple(), R :: tuple().
keymerge(Index, T1, L2) when is_integer(Index), Index > 0 ->
case L2 of
@@ -597,7 +599,7 @@ keymerge(Index, T1, L2) when is_integer(Index), Index > 0 ->
%% reverse(rkeymerge(I,reverse(A),reverse(B))) is equal to keymerge(I,A,B).
-spec rkeymerge(pos_integer(), [X], [Y]) ->
- [R] when is_subtype(X, tuple()), is_subtype(Y, tuple()), is_subtype(R, tuple()).
+ [R] when X :: tuple(), Y :: tuple(), R :: tuple().
rkeymerge(Index, T1, L2) when is_integer(Index), Index > 0 ->
case L2 of
@@ -609,7 +611,7 @@ rkeymerge(Index, T1, L2) when is_integer(Index), Index > 0 ->
lists:reverse(M, [])
end.
--spec ukeysort(pos_integer(), [T]) -> [T] when is_subtype(T, tuple()).
+-spec ukeysort(pos_integer(), [T]) -> [T] when T :: tuple().
ukeysort(I, L) when is_integer(I), I > 0 ->
case L of
@@ -675,7 +677,7 @@ ukeysort_1(_I, X, _EX, []) ->
[X].
-spec ukeymerge(pos_integer(), [X], [Y]) ->
- [(X | Y)] when is_subtype(X, tuple()), is_subtype(Y, tuple()).
+ [(X | Y)] when X :: tuple(), Y :: tuple().
ukeymerge(Index, L1, T2) when is_integer(Index), Index > 0 ->
case L1 of
@@ -690,7 +692,7 @@ ukeymerge(Index, L1, T2) when is_integer(Index), Index > 0 ->
%% reverse(rukeymerge(I,reverse(A),reverse(B))) is equal to ukeymerge(I,A,B).
-spec rukeymerge(pos_integer(), [X], [Y]) ->
- [(X | Y)] when is_subtype(X, tuple()), is_subtype(Y, tuple()).
+ [(X | Y)] when X :: tuple(), Y :: tuple().
rukeymerge(Index, T1, L2) when is_integer(Index), Index > 0 ->
case L2 of
@@ -702,7 +704,7 @@ rukeymerge(Index, T1, L2) when is_integer(Index), Index > 0 ->
lists:reverse(M, [])
end.
--spec keymap(fun((_) -> _), pos_integer(), [tuple()]) -> [tuple()].
+-spec keymap(fun((term()) -> term()), pos_integer(), [tuple()]) -> [tuple()].
keymap(Fun, Index, [Tup|Tail]) ->
[setelement(Index, Tup, Fun(element(Index, Tup)))|keymap(Fun, Index, Tail)];
@@ -725,7 +727,7 @@ sort(Fun, [X, Y | T]) ->
fsplit_2(Y, X, Fun, T, [], [])
end.
--spec merge(fun((X, Y) -> boolean()), [X], [Y]) -> [_].
+-spec merge(fun((X, Y) -> boolean()), [X], [Y]) -> [(X | Y)].
merge(Fun, T1, [H2 | T2]) when is_function(Fun, 2) ->
lists:reverse(fmerge2_1(T1, H2, Fun, T2, []), []);
@@ -734,7 +736,7 @@ merge(Fun, T1, []) when is_function(Fun, 2) ->
%% reverse(rmerge(F,reverse(A),reverse(B))) is equal to merge(F,A,B).
--spec rmerge(fun((X, Y) -> boolean()), [X], [Y]) -> [_].
+-spec rmerge(fun((X, Y) -> boolean()), [X], [Y]) -> [(X | Y)].
rmerge(Fun, T1, [H2 | T2]) when is_function(Fun, 2) ->
lists:reverse(rfmerge2_1(T1, H2, Fun, T2, []), []);
@@ -768,7 +770,7 @@ usort_1(Fun, X, [Y | L]) ->
ufsplit_2(Y, L, Fun, [X])
end.
--spec umerge(fun((X, Y) -> boolean()), [X], [Y]) -> [_].
+-spec umerge(fun((X, Y) -> boolean()), [X], [Y]) -> [(X | Y)].
umerge(Fun, [], T2) when is_function(Fun, 2) ->
T2;
@@ -777,7 +779,7 @@ umerge(Fun, [H1 | T1], T2) when is_function(Fun, 2) ->
%% reverse(rumerge(F,reverse(A),reverse(B))) is equal to umerge(F,A,B).
--spec rumerge(fun((X, Y) -> boolean()), [X], [Y]) -> [_].
+-spec rumerge(fun((X, Y) -> boolean()), [X], [Y]) -> [(X | Y)].
rumerge(Fun, T1, []) when is_function(Fun, 2) ->
T1;
@@ -842,7 +844,7 @@ usort_1(X, []) ->
%% umerge(List) -> L
%% merges a list of sorted lists without duplicates, removes duplicates
--spec umerge([T]) -> [T].
+-spec umerge([[T]]) -> [T].
umerge(L) ->
umergel(L).
@@ -851,7 +853,7 @@ umerge(L) ->
%% merges three sorted lists X, Y and Z without duplicates,
%% removes duplicates
--spec umerge3([_], [_], [_]) -> [_].
+-spec umerge3([X], [Y], [Z]) -> [(X | Y | Z)].
umerge3(L1, [], L3) ->
umerge(L1, L3);
@@ -864,7 +866,7 @@ umerge3(L1, [H2 | T2], [H3 | T3]) ->
%% merges three reversed sorted lists X, Y and Z without duplicates,
%% removes duplicates
--spec rumerge3([_], [_], [_]) -> [_].
+-spec rumerge3([X], [Y], [Z]) -> [(X | Y | Z)].
rumerge3(L1, [], L3) ->
rumerge(L1, L3);
@@ -876,7 +878,7 @@ rumerge3(L1, [H2 | T2], [H3 | T3]) ->
%% umerge(X, Y) -> L
%% merges two sorted lists X and Y without duplicates, removes duplicates
--spec umerge([_], [_]) -> [_].
+-spec umerge([X], [Y]) -> [(X | Y)].
umerge([], T2) ->
T2;
@@ -889,7 +891,7 @@ umerge([H1 | T1], T2) ->
%% reverse(rumerge(reverse(A),reverse(B))) is equal to umerge(I,A,B).
--spec rumerge([_], [_]) -> [_].
+-spec rumerge([X], [Y]) -> [(X | Y)].
rumerge(T1, []) ->
T1;
@@ -952,13 +954,13 @@ flatmap(F, [Hd|Tail]) ->
F(Hd) ++ flatmap(F, Tail);
flatmap(F, []) when is_function(F, 1) -> [].
--spec foldl(fun((T, _) -> _), _, [T]) -> _.
+-spec foldl(fun((T, term()) -> term()), term(), [T]) -> term().
foldl(F, Accu, [Hd|Tail]) ->
foldl(F, F(Hd, Accu), Tail);
foldl(F, Accu, []) when is_function(F, 2) -> Accu.
--spec foldr(fun((T, _) -> _), _, [T]) -> _.
+-spec foldr(fun((T, term()) -> term()), term(), [T]) -> term().
foldr(F, Accu, [Hd|Tail]) ->
F(Hd, foldr(F, Accu, Tail));
@@ -998,14 +1000,14 @@ zf(F, [Hd|Tail]) ->
end;
zf(F, []) when is_function(F, 1) -> [].
--spec foreach(F :: fun((T) -> _), List :: [T]) -> 'ok'.
+-spec foreach(F :: fun((T) -> term()), List :: [T]) -> 'ok'.
foreach(F, [Hd|Tail]) ->
F(Hd),
foreach(F, Tail);
foreach(F, []) when is_function(F, 1) -> ok.
--spec mapfoldl(fun((T, _) -> {_, _}), _, [T]) -> {[_], _}.
+-spec mapfoldl(fun((A, term()) -> {B, term()}), term(), [A]) -> {[B], term()}.
mapfoldl(F, Accu0, [Hd|Tail]) ->
{R,Accu1} = F(Hd, Accu0),
@@ -1013,7 +1015,7 @@ mapfoldl(F, Accu0, [Hd|Tail]) ->
{[R|Rs],Accu2};
mapfoldl(F, Accu, []) when is_function(F, 2) -> {[],Accu}.
--spec mapfoldr(fun((T, _) -> {_, _}), _, [T]) -> {[_], _}.
+-spec mapfoldr(fun((A, term()) -> {B, term()}), term(), [A]) -> {[B], term()}.
mapfoldr(F, Accu0, [Hd|Tail]) ->
{Rs,Accu1} = mapfoldr(F, Accu0, Tail),
diff --git a/lib/stdlib/src/ms_transform.erl b/lib/stdlib/src/ms_transform.erl
index 78b1de6e16..a249dea525 100644
--- a/lib/stdlib/src/ms_transform.erl
+++ b/lib/stdlib/src/ms_transform.erl
@@ -43,6 +43,7 @@
-define(ERR_GENREMOTECALL,22).
-define(ERR_GENBINCONSTRUCT,23).
-define(ERR_GENDISALLOWEDOP,24).
+-define(WARN_SHADOW_VAR,50).
-define(ERR_GUARDMATCH,?ERR_GENMATCH+?ERROR_BASE_GUARD).
-define(ERR_BODYMATCH,?ERR_GENMATCH+?ERROR_BASE_BODY).
-define(ERR_GUARDLOCALCALL,?ERR_GENLOCALCALL+?ERROR_BASE_GUARD).
@@ -63,8 +64,13 @@
-define(ERR_BODYDISALLOWEDOP,?ERR_GENDISALLOWEDOP+?ERROR_BASE_BODY).
%%
-%% Called by compiler or ets/dbg:fun2ms when errors occur
+%% Called by compiler or ets/dbg:fun2ms when errors/warnings occur
%%
+format_error({?WARN_SHADOW_VAR,Name}) ->
+ lists:flatten(
+ io_lib:format("variable ~p shadowed in ms_transform fun head",
+ [Name]));
+
format_error(?ERR_NOFUN) ->
"Parameter of ets/dbg:fun2ms/1 is not a literal fun";
format_error(?ERR_ETS_HEAD) ->
@@ -182,7 +188,7 @@ format_error(Else) ->
%%
transform_from_shell(Dialect, Clauses, BoundEnvironment) ->
SaveFilename = setup_filename(),
- case catch ms_clause_list(1,Clauses,Dialect) of
+ case catch ms_clause_list(1,Clauses,Dialect,gb_sets:new()) of
{'EXIT',Reason} ->
cleanup_filename(SaveFilename),
exit(Reason);
@@ -207,6 +213,7 @@ transform_from_shell(Dialect, Clauses, BoundEnvironment) ->
%%
parse_transform(Forms, _Options) ->
SaveFilename = setup_filename(),
+ %io:format("Forms: ~p~n",[Forms]),
case catch forms(Forms) of
{'EXIT',Reason} ->
cleanup_filename(SaveFilename),
@@ -215,12 +222,31 @@ parse_transform(Forms, _Options) ->
{error, [{cleanup_filename(SaveFilename),
[{Line, ?MODULE, R}]}], []};
Else ->
- cleanup_filename(SaveFilename),
+ %io:format("Transformed into: ~p~n",[Else]),
+ case get_warnings() of
+ [] ->
+ cleanup_filename(SaveFilename),
+ Else;
+ WL ->
+ FName = cleanup_filename(SaveFilename) ,
+ WList = [ {FName, [{L, ?MODULE, R}]} || {L,R} <- WL ],
+ {warning, Else, WList}
+ end
+ end.
+
+get_warnings() ->
+ case get(warnings) of
+ undefined ->
+ [];
+ Else ->
Else
end.
+add_warning(Line,R) ->
+ put(warnings,[{Line,R}| get_warnings()]).
+
setup_filename() ->
- {erase(filename),erase(records)}.
+ {erase(filename),erase(records),erase(warnings)}.
put_filename(Name) ->
put(filename,Name).
@@ -235,7 +261,7 @@ get_records() ->
Else ->
Else
end.
-cleanup_filename({Old,OldRec}) ->
+cleanup_filename({Old,OldRec,OldWarnings}) ->
Ret = case erase(filename) of
undefined ->
"TOP_LEVEL";
@@ -248,6 +274,12 @@ cleanup_filename({Old,OldRec}) ->
Rec ->
put(records,Rec)
end,
+ case OldWarnings of
+ undefined ->
+ erase(warnings);
+ Warn ->
+ put(warnings,Warn)
+ end,
case Old of
undefined ->
Ret;
@@ -285,42 +317,77 @@ form({function,Line,Name0,Arity0,Clauses0}) ->
form(AnyOther) ->
AnyOther.
function(Name, Arity, Clauses0) ->
- Clauses1 = clauses(Clauses0),
+ {Clauses1,_} = clauses(Clauses0,gb_sets:new()),
{Name,Arity,Clauses1}.
-clauses([C0|Cs]) ->
- C1 = clause(C0),
- [C1|clauses(Cs)];
-clauses([]) -> [].
-clause({clause,Line,H0,G0,B0}) ->
- B1 = copy(B0),
- {clause,Line,H0,G0,B1}.
+clauses([C0|Cs],Bound) ->
+ {C1,Bound1} = clause(C0,Bound),
+ {C2,Bound2} = clauses(Cs,Bound1),
+ {[C1|C2],Bound2};
+clauses([],Bound) -> {[],Bound}.
+clause({clause,Line,H0,G0,B0},Bound) ->
+ {H1,Bound1} = copy(H0,Bound),
+ {B1,Bound2} = copy(B0,Bound1),
+ {{clause,Line,H1,G0,B1},Bound2}.
copy({call,Line,{remote,_Line2,{atom,_Line3,ets},{atom,_Line4,fun2ms}},
- As0}) ->
- transform_call(ets,Line,As0);
+ As0},Bound) ->
+ {transform_call(ets,Line,As0,Bound),Bound};
copy({call,Line,{remote,_Line2,{record_field,_Line3,
{atom,_Line4,''},{atom,_Line5,ets}},
- {atom,_Line6,fun2ms}}, As0}) ->
+ {atom,_Line6,fun2ms}}, As0},Bound) ->
%% Packages...
- transform_call(ets,Line,As0);
+ {transform_call(ets,Line,As0,Bound),Bound};
copy({call,Line,{remote,_Line2,{atom,_Line3,dbg},{atom,_Line4,fun2ms}},
- As0}) ->
- transform_call(dbg,Line,As0);
-copy(T) when is_tuple(T) ->
- list_to_tuple(copy_list(tuple_to_list(T)));
-copy(L) when is_list(L) ->
- copy_list(L);
-copy(AnyOther) ->
- AnyOther.
+ As0},Bound) ->
+ {transform_call(dbg,Line,As0,Bound),Bound};
+copy({match,Line,A,B},Bound) ->
+ {B1,Bound1} = copy(B,Bound),
+ {A1,Bound2} = copy(A,Bound),
+ {{match,Line,A1,B1},gb_sets:union(Bound1,Bound2)};
+copy({var,_Line,'_'} = VarDef,Bound) ->
+ {VarDef,Bound};
+copy({var,_Line,Name} = VarDef,Bound) ->
+ Bound1 = gb_sets:add(Name,Bound),
+ {VarDef,Bound1};
+copy({'fun',Line,{clauses,Clauses}},Bound) -> % Dont export bindings from funs
+ {NewClauses,_IgnoredBindings} = copy_list(Clauses,Bound),
+ {{'fun',Line,{clauses,NewClauses}},Bound};
+copy({'case',Line,Of,ClausesList},Bound) -> % Dont export bindings from funs
+ {NewOf,NewBind0} = copy(Of,Bound),
+ {NewClausesList,NewBindings} = copy_case_clauses(ClausesList,NewBind0,[]),
+ {{'case',Line,NewOf,NewClausesList},NewBindings};
+copy(T,Bound) when is_tuple(T) ->
+ {L,Bound1} = copy_list(tuple_to_list(T),Bound),
+ {list_to_tuple(L),Bound1};
+copy(L,Bound) when is_list(L) ->
+ copy_list(L,Bound);
+copy(AnyOther,Bound) ->
+ {AnyOther,Bound}.
-copy_list([H|T]) ->
- [copy(H)|copy_list(T)];
-copy_list([]) ->
- [].
+copy_case_clauses([],Bound,AddSets) ->
+ ReallyAdded = gb_sets:intersection(AddSets),
+ {[],gb_sets:union(Bound,ReallyAdded)};
+copy_case_clauses([{clause,Line,Match,Guard,Clauses}|T],Bound,AddSets) ->
+ {NewMatch,MatchBinds} = copy(Match,Bound),
+ {NewGuard,GuardBinds} = copy(Guard,MatchBinds), %% Really no new binds
+ {NewClauses,AllBinds} = copy(Clauses,GuardBinds),
+ %% To limit the setsizes, I subtract what I had before the case clause
+ %% and add it in the end
+ AddedBinds = gb_sets:subtract(AllBinds,Bound),
+ {NewTail,ExportedBindings} =
+ copy_case_clauses(T,Bound,[AddedBinds | AddSets]),
+ {[{clause,Line,NewMatch,NewGuard,NewClauses}|NewTail],ExportedBindings}.
-transform_call(Type,_Line,[{'fun',Line2,{clauses, ClauseList}}]) ->
- ms_clause_list(Line2, ClauseList,Type);
-transform_call(_Type,Line,_NoAbstractFun) ->
+copy_list([H|T],Bound) ->
+ {C1,Bound1} = copy(H,Bound),
+ {C2,Bound2} = copy_list(T,Bound1),
+ {[C1|C2],Bound2};
+copy_list([],Bound) ->
+ {[],Bound}.
+
+transform_call(Type,_Line,[{'fun',Line2,{clauses, ClauseList}}],Bound) ->
+ ms_clause_list(Line2, ClauseList,Type,Bound);
+transform_call(_Type,Line,_NoAbstractFun,_) ->
throw({error,Line,?ERR_NOFUN}).
% Fixup semicolons in guards
@@ -329,18 +396,19 @@ ms_clause_expand({clause, Line, Parameters, Guard = [_,_|_], Body}) ->
ms_clause_expand(_Other) ->
false.
-ms_clause_list(Line,[H|T],Type) ->
+ms_clause_list(Line,[H|T],Type,Bound) ->
case ms_clause_expand(H) of
NewHead when is_list(NewHead) ->
- ms_clause_list(Line,NewHead ++ T, Type);
+ ms_clause_list(Line,NewHead ++ T, Type, Bound);
false ->
- {cons, Line, ms_clause(H,Type), ms_clause_list(Line, T,Type)}
+ {cons, Line, ms_clause(H, Type, Bound),
+ ms_clause_list(Line, T, Type, Bound)}
end;
-ms_clause_list(Line,[],_) ->
+ms_clause_list(Line,[],_,_) ->
{nil,Line}.
-ms_clause({clause, Line, Parameters, Guards, Body},Type) ->
+ms_clause({clause, Line, Parameters, Guards, Body},Type,Bound) ->
check_type(Line,Parameters,Type),
- {MSHead,Bindings} = transform_head(Parameters),
+ {MSHead,Bindings} = transform_head(Parameters,Bound),
MSGuards = transform_guards(Line, Guards, Bindings),
MSBody = transform_body(Line,Body,Bindings),
{tuple, Line, [MSHead,MSGuards,MSBody]}.
@@ -627,29 +695,31 @@ tg(Other,B) ->
Element = io_lib:format("unknown element ~w", [Other]),
throw({error,unknown,{?ERR_GENELEMENT+B#tgd.eb,Element}}).
-transform_head([V]) ->
+transform_head([V],OuterBound) ->
Bind = cre_bind(),
- {NewV,NewBind} = toplevel_head_match(V,Bind),
- th(NewV,NewBind).
+ {NewV,NewBind} = toplevel_head_match(V,Bind,OuterBound),
+ th(NewV,NewBind,OuterBound).
-toplevel_head_match({match,_,{var,_,VName},Expr},B) ->
+toplevel_head_match({match,Line,{var,_,VName},Expr},B,OB) ->
+ warn_var_clash(Line,VName,OB),
{Expr,new_bind({VName,'$_'},B)};
-toplevel_head_match({match,_,Expr,{var,_,VName}},B) ->
+toplevel_head_match({match,Line,Expr,{var,_,VName}},B,OB) ->
+ warn_var_clash(Line,VName,OB),
{Expr,new_bind({VName,'$_'},B)};
-toplevel_head_match(Other,B) ->
+toplevel_head_match(Other,B,_OB) ->
{Other,B}.
-th({record,Line,RName,RFields},B) ->
+th({record,Line,RName,RFields},B,OB) ->
% youch...
RDefs = get_records(),
{KeyList0,NewB} = lists:foldl(fun({record_field,_,{atom,_,Key},Value},
{L,B0}) ->
- {NV,B1} = th(Value,B0),
+ {NV,B1} = th(Value,B0,OB),
{[{Key,NV}|L],B1};
({record_field,_,{var,_,'_'},Value},
{L,B0}) ->
- {NV,B1} = th(Value,B0),
+ {NV,B1} = th(Value,B0,OB),
{[{{default},NV}|L],B1};
(_,_) ->
throw({error,Line,{?ERR_HEADBADREC,
@@ -692,9 +762,9 @@ th({record,Line,RName,RFields},B) ->
_ ->
throw({error,Line,{?ERR_HEADBADREC,RName}})
end;
-th({match,Line,_,_},_) ->
+th({match,Line,_,_},_,_) ->
throw({error,Line,?ERR_HEADMATCH});
-th({atom,Line,A},B) ->
+th({atom,Line,A},B,_OB) ->
case atom_to_list(A) of
[$$|NL] ->
case (catch list_to_integer(NL)) of
@@ -706,10 +776,11 @@ th({atom,Line,A},B) ->
_ ->
{{atom,Line,A},B}
end;
-th({bin_element,_Line0,{var, Line, A},_,_},_) ->
+th({bin_element,_Line0,{var, Line, A},_,_},_,_) ->
throw({error,Line,{?ERR_HEADBINMATCH,A}});
-th({var,Line,Name},B) ->
+th({var,Line,Name},B,OB) ->
+ warn_var_clash(Line,Name,OB),
case lkup_bind(Name,B) of
undefined ->
NewB = new_bind(Name,B),
@@ -717,16 +788,24 @@ th({var,Line,Name},B) ->
Trans ->
{{atom,Line,Trans},B}
end;
-th([H|T],B) ->
- {NH,NB} = th(H,B),
- {NT,NNB} = th(T,NB),
+th([H|T],B,OB) ->
+ {NH,NB} = th(H,B,OB),
+ {NT,NNB} = th(T,NB,OB),
{[NH|NT],NNB};
-th(T,B) when is_tuple(T) ->
- {L,NB} = th(tuple_to_list(T),B),
+th(T,B,OB) when is_tuple(T) ->
+ {L,NB} = th(tuple_to_list(T),B,OB),
{list_to_tuple(L),NB};
-th(Nonstruct,B) ->
+th(Nonstruct,B,_OB) ->
{Nonstruct,B}.
+warn_var_clash(Line,Name,OuterBound) ->
+ case gb_sets:is_member(Name,OuterBound) of
+ true ->
+ add_warning(Line,{?WARN_SHADOW_VAR,Name});
+ _ ->
+ ok
+ end.
+
%% Could be more efficient...
check_multi_field(_, _, [], _) ->
ok;
diff --git a/lib/stdlib/src/orddict.erl b/lib/stdlib/src/orddict.erl
index c7b52b933e..8a13992785 100644
--- a/lib/stdlib/src/orddict.erl
+++ b/lib/stdlib/src/orddict.erl
@@ -151,7 +151,7 @@ map(F, [{Key,Val}|D]) ->
[{Key,F(Key, Val)}|map(F, D)];
map(F, []) when is_function(F, 2) -> [].
--spec filter(fun((term(), term()) -> term()), orddict()) -> orddict().
+-spec filter(fun((term(), term()) -> boolean()), orddict()) -> orddict().
filter(F, [{Key,Val}=E|D]) ->
case F(Key, Val) of
diff --git a/lib/stdlib/src/ordsets.erl b/lib/stdlib/src/ordsets.erl
index 05041c15f1..4c72e351d0 100644
--- a/lib/stdlib/src/ordsets.erl
+++ b/lib/stdlib/src/ordsets.erl
@@ -26,12 +26,14 @@
-export([subtract/2,is_subset/2]).
-export([fold/3,filter/2]).
+-export_type([ordset/1]).
+
-type ordset(T) :: [T].
%% new() -> Set.
%% Return a new empty ordered set.
--spec new() -> ordset(term()).
+-spec new() -> [].
new() -> [].
@@ -84,7 +86,7 @@ is_element(_, []) -> false.
%% add_element(Element, OrdSet) -> OrdSet.
%% Return OrdSet with Element inserted in it.
--spec add_element(term(), ordset(_)) -> ordset(_).
+-spec add_element(E, ordset(T)) -> [T | E,...].
add_element(E, [H|Es]) when E > H -> [H|add_element(E, Es)];
add_element(E, [H|_]=Set) when E < H -> [E|Set];
@@ -94,7 +96,7 @@ add_element(E, []) -> [E].
%% del_element(Element, OrdSet) -> OrdSet.
%% Return OrdSet but with Element removed.
--spec del_element(term(), ordset(_)) -> ordset(_).
+-spec del_element(term(), ordset(T)) -> ordset(T).
del_element(E, [H|Es]) when E > H -> [H|del_element(E, Es)];
del_element(E, [H|_]=Set) when E < H -> Set;
@@ -104,7 +106,7 @@ del_element(_, []) -> [].
%% union(OrdSet1, OrdSet2) -> OrdSet
%% Return the union of OrdSet1 and OrdSet2.
--spec union(ordset(_), ordset(_)) -> ordset(_).
+-spec union(ordset(T1), ordset(T2)) -> ordset(T1 | T2).
union([E1|Es1], [E2|_]=Set2) when E1 < E2 ->
[E1|union(Es1, Set2)];
@@ -118,7 +120,7 @@ union(Es1, []) -> Es1.
%% union([OrdSet]) -> OrdSet
%% Return the union of the list of ordered sets.
--spec union([ordset(_)]) -> ordset(_).
+-spec union([ordset(T)]) -> ordset(T).
union([S1,S2|Ss]) ->
union1(union(S1, S2), Ss);
@@ -147,7 +149,7 @@ intersection(_, []) ->
%% intersection([OrdSet]) -> OrdSet.
%% Return the intersection of the list of ordered sets.
--spec intersection([ordset(_)]) -> ordset(_).
+-spec intersection([ordset(_),...]) -> ordset(_).
intersection([S1,S2|Ss]) ->
intersection1(intersection(S1, S2), Ss);
@@ -206,7 +208,7 @@ is_subset(_, []) -> false.
%% fold(Fun, Accumulator, OrdSet) -> Accumulator.
%% Fold function Fun over all elements in OrdSet and return Accumulator.
--spec fold(fun((_, _) -> _), _, ordset(_)) -> _.
+-spec fold(fun((T, term()) -> term()), term(), ordset(T)) -> term().
fold(F, Acc, Set) ->
lists:foldl(F, Acc, Set).
@@ -214,7 +216,7 @@ fold(F, Acc, Set) ->
%% filter(Fun, OrdSet) -> OrdSet.
%% Filter OrdSet with Fun.
--spec filter(fun((_) -> boolean()), ordset(_)) -> ordset(_).
+-spec filter(fun((T) -> boolean()), ordset(T)) -> ordset(T).
filter(F, Set) ->
lists:filter(F, Set).
diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl
index 1514414e48..5c52dfcbf0 100644
--- a/lib/stdlib/src/otp_internal.erl
+++ b/lib/stdlib/src/otp_internal.erl
@@ -361,6 +361,12 @@ obsolete_1(erlang, concat_binary, 1) ->
obsolete_1(ssl, peercert, 2) ->
{deprecated,"deprecated (will be removed in R15A); use ssl:peercert/1 and public_key:pkix_decode_cert/2 instead"};
+%% Added in R14B.
+obsolete_1(public_key, pem_to_der, 1) ->
+ {deprecated,"deprecated (will be removed in R15A); use file:read_file/1 and public_key:pem_decode/1"};
+obsolete_1(public_key, decode_private_key, A) when A =:= 1; A =:= 2 ->
+ {deprecated,{public_key,pem_entry_decode,1},"R15A"};
+
obsolete_1(_, _, _) ->
no.
diff --git a/lib/stdlib/src/qlc.erl b/lib/stdlib/src/qlc.erl
index 6e48d95973..bc6944e520 100644
--- a/lib/stdlib/src/qlc.erl
+++ b/lib/stdlib/src/qlc.erl
@@ -24,6 +24,8 @@
%% External exports
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([parse_transform/2, transform_from_evaluator/2]).
-export([q/1, q/2]).
diff --git a/lib/stdlib/src/string.erl b/lib/stdlib/src/string.erl
index 6636a03f06..c987c224db 100644
--- a/lib/stdlib/src/string.erl
+++ b/lib/stdlib/src/string.erl
@@ -201,7 +201,7 @@ chars(C, 0, Tail) when is_integer(C) ->
-spec copies(string(), non_neg_integer()) -> string().
-copies(CharList, Num) when is_list(CharList), Num >= 0 ->
+copies(CharList, Num) when is_list(CharList), is_integer(Num), Num >= 0 ->
copies(CharList, Num, []).
copies(_CharList, 0, R) ->
diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl
index f5d5441184..5bdd1a8672 100644
--- a/lib/stdlib/src/supervisor.erl
+++ b/lib/stdlib/src/supervisor.erl
@@ -33,7 +33,9 @@
-export([init/1, handle_call/3, handle_info/2, terminate/2, code_change/3]).
-export([handle_cast/2]).
--export_type([child_spec/0, strategy/0]).
+%%--------------------------------------------------------------------------
+
+-export_type([child_spec/0, del_err/0, startchild_ret/0, strategy/0]).
%%--------------------------------------------------------------------------
@@ -77,6 +79,10 @@
-define(is_simple(State), State#state.strategy =:= simple_one_for_one).
+%%--------------------------------------------------------------------------
+
+-spec behaviour_info(atom()) -> 'undefined' | [{atom(), arity()}].
+
behaviour_info(callbacks) ->
[{init,1}];
behaviour_info(_Other) ->
@@ -160,11 +166,13 @@ check_childspecs(X) -> {error, {badarg, X}}.
%%%
%%% ---------------------------------------------------
+-type init_sup_name() :: sup_name() | 'self'.
+
-type stop_rsn() :: 'shutdown' | {'bad_return', {module(),'init', term()}}
| {'bad_start_spec', term()} | {'start_spec', term()}
| {'supervisor_data', term()}.
--spec init({sup_name(), module(), [term()]}) ->
+-spec init({init_sup_name(), module(), [term()]}) ->
{'ok', state()} | 'ignore' | {'stop', stop_rsn()}.
init({SupName, Mod, Args}) ->
@@ -184,7 +192,7 @@ init({SupName, Mod, Args}) ->
Error ->
{stop, {bad_return, {Mod, init, Error}}}
end.
-
+
init_children(State, StartSpec) ->
SupName = State#state.name,
case check_startspec(StartSpec) of
diff --git a/lib/stdlib/src/timer.erl b/lib/stdlib/src/timer.erl
index 24e14caa69..b456c5d6c1 100644
--- a/lib/stdlib/src/timer.erl
+++ b/lib/stdlib/src/timer.erl
@@ -33,6 +33,9 @@
%% internal exports for test purposes only
-export([get_status/0]).
+%% types which can be used by other modules
+-export_type([tref/0]).
+
%% Max
-define(MAX_TIMEOUT, 16#0800000).
-define(TIMER_TAB, timer_tab).
diff --git a/lib/stdlib/test/dets_SUITE.erl b/lib/stdlib/test/dets_SUITE.erl
index 760e610e00..8b18ef5664 100644
--- a/lib/stdlib/test/dets_SUITE.erl
+++ b/lib/stdlib/test/dets_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -50,7 +50,8 @@
otp_4208/1, otp_4989/1, many_clients/1, otp_4906/1, otp_5402/1,
simultaneous_open/1, insert_new/1, repair_continuation/1,
otp_5487/1, otp_6206/1, otp_6359/1, otp_4738/1, otp_7146/1,
- otp_8070/1]).
+ otp_8070/1, otp_8856/1, otp_8898/1, otp_8899/1, otp_8903/1,
+ otp_8923/1]).
-export([dets_dirty_loop/0]).
@@ -108,7 +109,8 @@ all(suite) ->
cache_duplicate_bags_v9, otp_4208, otp_4989, many_clients,
otp_4906, otp_5402, simultaneous_open, insert_new,
repair_continuation, otp_5487, otp_6206, otp_6359, otp_4738,
- otp_7146, otp_8070]}
+ otp_7146, otp_8070, otp_8856, otp_8898, otp_8899, otp_8903,
+ otp_8923]}
end.
not_run(suite) -> [];
@@ -2935,6 +2937,57 @@ ets_init(Tab, N) ->
ets:insert(Tab, {N,N}),
ets_init(Tab, N - 1).
+otp_8898(doc) ->
+ ["OTP-8898. Truncated Dets file."];
+otp_8898(suite) ->
+ [];
+otp_8898(Config) when is_list(Config) ->
+ Tab = otp_8898,
+ ?line FName = filename(Tab, Config),
+
+ Server = self(),
+
+ ?line file:delete(FName),
+ ?line {ok, _} = dets:open_file(Tab,[{file, FName}]),
+ ?line [P1,P2,P3] = new_clients(3, Tab),
+
+ Seq = [{P1,[sync]},{P2,[{lookup,1,[]}]},{P3,[{insert,{1,b}}]}],
+ ?line atomic_requests(Server, Tab, [[]], Seq),
+ ?line true = get_replies([{P1,ok},{P2,ok},{P3,ok}]),
+ ?line ok = dets:close(Tab),
+ ?line {ok, _} = dets:open_file(Tab,[{file, FName}]),
+ ?line file:delete(FName),
+
+ ok.
+
+otp_8899(doc) ->
+ ["OTP-8899. Several clients. Updated Head was ignored."];
+otp_8899(suite) ->
+ [];
+otp_8899(Config) when is_list(Config) ->
+ Tab = many_clients,
+ ?line FName = filename(Tab, Config),
+
+ Server = self(),
+
+ ?line file:delete(FName),
+ ?line {ok, _} = dets:open_file(Tab,[{file, FName},{version,9}]),
+ ?line [P1,P2,P3,P4] = new_clients(4, Tab),
+
+ MC = [Tab],
+ Seq6a = [{P1,[{insert,[{used_to_be_skipped_by,match}]},
+ {lookup,1,[{1,a}]}]},
+ {P2,[{verbose,true,MC}]},
+ {P3,[{lookup,1,[{1,a}]}]}, {P4,[{verbose,true,MC}]}],
+ ?line atomic_requests(Server, Tab, [[{1,a},{2,b},{3,c}]], Seq6a),
+ ?line true = get_replies([{P1,ok}, {P2,ok}, {P3,ok}, {P4,ok}]),
+ ?line [{1,a},{2,b},{3,c},{used_to_be_skipped_by,match}] =
+ lists:sort(dets:match_object(Tab, '_')),
+ ?line _ = dets:close(Tab),
+ ?line file:delete(FName),
+
+ ok.
+
many_clients(doc) ->
["Several clients accessing a table simultaneously."];
many_clients(suite) ->
@@ -3071,6 +3124,11 @@ client(S, Tab) ->
eval([], _Tab) ->
ok;
+eval([{verbose,Bool,Expected} | L], Tab) ->
+ ?line case dets:verbose(Bool) of
+ Expected -> eval(L, Tab);
+ Error -> {error, {verbose,Error}}
+ end;
eval([sync | L], Tab) ->
?line case dets:sync(Tab) of
ok -> eval(L, Tab);
@@ -3701,6 +3759,87 @@ otp_8070(Config) when is_list(Config) ->
file:delete(File),
ok.
+otp_8856(doc) ->
+ ["OTP-8856. insert_new() bug."];
+otp_8856(suite) ->
+ [];
+otp_8856(Config) when is_list(Config) ->
+ Tab = otp_8856,
+ File = filename(Tab, Config),
+ file:delete(File),
+ Me = self(),
+ ?line {ok, _} = dets:open_file(Tab, [{type, bag}, {file, File}]),
+ spawn(fun()-> Me ! {1, dets:insert(Tab, [])} end),
+ spawn(fun()-> Me ! {2, dets:insert_new(Tab, [])} end),
+ ?line ok = dets:close(Tab),
+ ?line receive {1, ok} -> ok end,
+ ?line receive {2, true} -> ok end,
+ file:delete(File),
+
+ ?line {ok, _} = dets:open_file(Tab, [{type, set}, {file, File}]),
+ spawn(fun() -> dets:delete(Tab, 0) end),
+ spawn(fun() -> Me ! {3, dets:insert_new(Tab, {0,0})} end),
+ ?line ok = dets:close(Tab),
+ ?line receive {3, true} -> ok end,
+ file:delete(File),
+ ok.
+
+otp_8903(doc) ->
+ ["OTP-8903. bchunk/match/select bug."];
+otp_8903(suite) ->
+ [];
+otp_8903(Config) when is_list(Config) ->
+ Tab = otp_8903,
+ File = filename(Tab, Config),
+ ?line {ok,T} = dets:open_file(bug, [{file,File}]),
+ ?line ok = dets:insert(T, [{1,a},{2,b},{3,c}]),
+ ?line dets:safe_fixtable(T, true),
+ ?line {[_],C1} = dets:match_object(T, '_', 1),
+ ?line {BC1,_D} = dets:bchunk(T, start),
+ ?line ok = dets:close(T),
+ ?line {'EXIT', {badarg, _}} = (catch {foo,dets:match_object(C1)}),
+ ?line {'EXIT', {badarg, _}} = (catch {foo,dets:bchunk(T, BC1)}),
+ ?line {ok,T} = dets:open_file(bug, [{file,File}]),
+ ?line false = dets:info(T, safe_fixed),
+ ?line {'EXIT', {badarg, _}} = (catch {foo,dets:match_object(C1)}),
+ ?line {'EXIT', {badarg, _}} = (catch {foo,dets:bchunk(T, BC1)}),
+ ?line ok = dets:close(T),
+ file:delete(File),
+ ok.
+
+otp_8923(doc) ->
+ ["OTP-8923. rehash due to lookup after initialization."];
+otp_8923(suite) ->
+ [];
+otp_8923(Config) when is_list(Config) ->
+ Tab = otp_8923,
+ File = filename(Tab, Config),
+ %% Create a file with more than 256 keys:
+ file:delete(File),
+ Bin = list_to_binary([ 0 || _ <- lists:seq(1, 400) ]),
+ BigBin = list_to_binary([ 0 ||_ <- lists:seq(1, 4000)]),
+ Ets = ets:new(temp, [{keypos,1}]),
+ ?line [ true = ets:insert(Ets, {C,Bin}) || C <- lists:seq(1, 700) ],
+ ?line true = ets:insert(Ets, {helper_data,BigBin}),
+ ?line true = ets:insert(Ets, {prim_btree,BigBin}),
+ ?line true = ets:insert(Ets, {sec_btree,BigBin}),
+ %% Note: too few slots; re-hash will take place
+ ?line {ok, Tab} = dets:open_file(Tab, [{file,File}]),
+ ?line Tab = ets:to_dets(Ets, Tab),
+ ?line ok = dets:close(Tab),
+ ?line true = ets:delete(Ets),
+
+ ?line {ok,Ref} = dets:open_file(File),
+ ?line [{1,_}] = dets:lookup(Ref, 1),
+ ?line ok = dets:close(Ref),
+
+ ?line {ok,Ref2} = dets:open_file(File),
+ ?line [{helper_data,_}] = dets:lookup(Ref2, helper_data),
+ ?line ok = dets:close(Ref2),
+
+ file:delete(File),
+ ok.
+
%%
%% Parts common to several test cases
%%
diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl
index e31dfdd764..e9fb932632 100644
--- a/lib/stdlib/test/epp_SUITE.erl
+++ b/lib/stdlib/test/epp_SUITE.erl
@@ -24,7 +24,7 @@
variable/1, variable_1/1, otp_4870/1, otp_4871/1, otp_5362/1,
pmod/1, not_circular/1, skip_header/1, otp_6277/1, otp_7702/1,
otp_8130/1, overload_mac/1, otp_8388/1, otp_8470/1, otp_8503/1,
- otp_8562/1, otp_8665/1]).
+ otp_8562/1, otp_8665/1, otp_8911/1]).
-export([epp_parse_erl_form/2]).
@@ -64,7 +64,7 @@ all(doc) ->
all(suite) ->
[rec_1, upcase_mac, predef_mac, variable, otp_4870, otp_4871, otp_5362,
pmod, not_circular, skip_header, otp_6277, otp_7702, otp_8130,
- overload_mac, otp_8388, otp_8470, otp_8503, otp_8562, otp_8665].
+ overload_mac, otp_8388, otp_8470, otp_8503, otp_8562, otp_8665, otp_8911].
rec_1(doc) ->
["Recursive macros hang or crash epp (OTP-1398)."];
@@ -1197,6 +1197,40 @@ otp_8562(Config) when is_list(Config) ->
?line [] = compile(Config, Cs),
ok.
+otp_8911(doc) ->
+ ["OTP-8911. -file and file inclusion bug"];
+otp_8911(suite) ->
+ [];
+otp_8911(Config) when is_list(Config) ->
+ ?line {ok, CWD} = file:get_cwd(),
+ ?line ok = file:set_cwd(?config(priv_dir, Config)),
+
+ File = "i.erl",
+ Cont = <<"-module(i).
+ -compile(export_all).
+ -file(\"fil1\", 100).
+ -include(\"i1.erl\").
+ t() ->
+ a.
+ ">>,
+ ?line ok = file:write_file(File, Cont),
+ Incl = <<"-file(\"fil2\", 35).
+ t1() ->
+ b.
+ ">>,
+ File1 = "i1.erl",
+ ?line ok = file:write_file(File1, Incl),
+
+ ?line {ok, i} = cover:compile(File),
+ ?line a = i:t(),
+ ?line {ok,[{{i,6},1}]} = cover:analyse(i, calls, line),
+ ?line cover:stop(),
+
+ file:delete(File),
+ file:delete(File1),
+ ?line file:set_cwd(CWD),
+ ok.
+
otp_8665(doc) ->
["OTP-8665. Bugfix premature end."];
otp_8665(suite) ->
diff --git a/lib/stdlib/test/escript_SUITE.erl b/lib/stdlib/test/escript_SUITE.erl
index 77fd190e45..162ca6006f 100644
--- a/lib/stdlib/test/escript_SUITE.erl
+++ b/lib/stdlib/test/escript_SUITE.erl
@@ -31,6 +31,7 @@
epp/1,
create_and_extract/1,
foldl/1,
+ overflow/1,
verify_sections/3
]).
@@ -48,7 +49,8 @@ all(suite) ->
archive_script,
epp,
create_and_extract,
- foldl
+ foldl,
+ overflow
].
init_per_testcase(_Case, Config) ->
@@ -736,6 +738,17 @@ emulate_escript_foldl(Fun, Acc, File) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+overflow(Config) when is_list(Config) ->
+ Data = ?config(data_dir, Config),
+ Dir = filename:absname(Data), %Get rid of trailing slash.
+ ?line run(Dir, "arg_overflow",
+ [<<"ExitCode:0">>]),
+ ?line run(Dir, "linebuf_overflow",
+ [<<"ExitCode:0">>]),
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
run(Dir, Cmd0, Expected0) ->
Expected = iolist_to_binary(expected_output(Expected0, Dir)),
Cmd = case os:type() of
diff --git a/lib/stdlib/test/escript_SUITE_data/arg_overflow b/lib/stdlib/test/escript_SUITE_data/arg_overflow
new file mode 100755
index 0000000000..dd5accc051
--- /dev/null
+++ b/lib/stdlib/test/escript_SUITE_data/arg_overflow
@@ -0,0 +1,5 @@
+#! /usr/bin/env escript
+%% -*- erlang -*-
+%%!x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x
+main(_) ->
+ halt(0).
diff --git a/lib/stdlib/test/escript_SUITE_data/linebuf_overflow b/lib/stdlib/test/escript_SUITE_data/linebuf_overflow
new file mode 100755
index 0000000000..33133c1ce9
--- /dev/null
+++ b/lib/stdlib/test/escript_SUITE_data/linebuf_overflow
@@ -0,0 +1,5 @@
+#! /usr/bin/env escript
+%% -*- erlang -*-
+%%!xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+main(_) ->
+ halt(0).
diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl
index 5d7e558601..7f39dbe21f 100644
--- a/lib/stdlib/test/ets_SUITE.erl
+++ b/lib/stdlib/test/ets_SUITE.erl
@@ -94,6 +94,8 @@
do_heavy_concurrent/1
]).
+-export([t_select_reverse/1]).
+
-include("test_server.hrl").
init_per_testcase(Case, Config) ->
@@ -128,7 +130,7 @@ all(suite) ->
match_heavy, fold, member,
t_delete_object, t_init_table, t_whitebox,
t_delete_all_objects, t_insert_list, t_test_ms,
- t_select_delete, t_ets_dets, memory,
+ t_select_delete, t_ets_dets, memory, t_select_reverse,
t_bucket_disappears,
select_fail,t_insert_new, t_repair_continuation, otp_5340, otp_6338,
otp_6842_select_1000, otp_7665, otp_8732,
@@ -393,7 +395,7 @@ memory(Config) when is_list(Config) ->
?line erts_debug:set_internal_state(available_internal_state, true),
?line ok = chk_normal_tab_struct_size(),
?line L = [T1,T2,T3,T4] = fill_sets_int(1000),
- ?line XRes1 = adjust_xmem(L, {14862,14072,14072,14078}),
+ ?line XRes1 = adjust_xmem(L, {13862,13072,13072,13078}),
?line Res1 = {?S(T1),?S(T2),?S(T3),?S(T4)},
?line lists:foreach(fun(T) ->
Before = ets:info(T,size),
@@ -404,7 +406,7 @@ memory(Config) when is_list(Config) ->
[Key, ets:info(T,type), Before, ets:info(T,size), Objs])
end,
L),
- ?line XRes2 = adjust_xmem(L, {14851,14062,14052,14058}),
+ ?line XRes2 = adjust_xmem(L, {13852,13063,13054,13060}),
?line Res2 = {?S(T1),?S(T2),?S(T3),?S(T4)},
?line lists:foreach(fun(T) ->
Before = ets:info(T,size),
@@ -415,7 +417,7 @@ memory(Config) when is_list(Config) ->
[Key, ets:info(T,type), Before, ets:info(T,size), Objs])
end,
L),
- ?line XRes3 = adjust_xmem(L, {14840,14052,14032,14038}),
+ ?line XRes3 = adjust_xmem(L, {13842,13054,13036,13042}),
?line Res3 = {?S(T1),?S(T2),?S(T3),?S(T4)},
?line lists:foreach(fun(T) ->
?line ets:delete_all_objects(T)
@@ -788,6 +790,67 @@ t_test_ms(Config) when is_list(Config) ->
?line true = (if is_list(String) -> true; true -> false end),
?line verify_etsmem(EtsMem).
+t_select_reverse(doc) ->
+ ["Test the select reverse BIF's"];
+t_select_reverse(suite) ->
+ [];
+t_select_reverse(Config) when is_list(Config) ->
+ ?line Table = ets:new(xxx, [ordered_set]),
+ ?line filltabint(Table,1000),
+ ?line A = lists:reverse(ets:select(Table,[{{'$1', '_'},
+ [{'>',
+ {'rem',
+ '$1', 5},
+ 2}],
+ ['$_']}])),
+ ?line A = ets:select_reverse(Table,[{{'$1', '_'},
+ [{'>',
+ {'rem',
+ '$1', 5},
+ 2}],
+ ['$_']}]),
+ ?line A = reverse_chunked(Table,[{{'$1', '_'},
+ [{'>',
+ {'rem',
+ '$1', 5},
+ 2}],
+ ['$_']}],3),
+ % A set/bag/duplicate_bag should get the same result regardless
+ % of select or select_reverse
+ ?line Table2 = ets:new(xxx, [set]),
+ ?line filltabint(Table2,1000),
+ ?line Table3 = ets:new(xxx, [bag]),
+ ?line filltabint(Table3,1000),
+ ?line Table4 = ets:new(xxx, [duplicate_bag]),
+ ?line filltabint(Table4,1000),
+ ?line lists:map(fun(Tab) ->
+ B = ets:select(Tab,[{{'$1', '_'},
+ [{'>',
+ {'rem',
+ '$1', 5},
+ 2}],
+ ['$_']}]),
+ B = ets:select_reverse(Tab,[{{'$1', '_'},
+ [{'>',
+ {'rem',
+ '$1', 5},
+ 2}],
+ ['$_']}])
+ end,[Table2, Table3, Table4]),
+ ok.
+
+
+
+reverse_chunked(T,MS,N) ->
+ do_reverse_chunked(ets:select_reverse(T,MS,N),[]).
+
+do_reverse_chunked('$end_of_table',Acc) ->
+ lists:reverse(Acc);
+do_reverse_chunked({L,C},Acc) ->
+ NewAcc = lists:reverse(L)++Acc,
+ do_reverse_chunked(ets:select_reverse(C), NewAcc).
+
+
t_select_delete(doc) ->
["Test the ets:select_delete/2 and ets:select_count/2 BIF's"];
t_select_delete(suite) ->
@@ -3942,7 +4005,7 @@ do_lookup_element(Tab, N, M) ->
end.
-heavy_concurrent(Config) ->
+heavy_concurrent(_Config) ->
repeat_for_opts(do_heavy_concurrent).
do_heavy_concurrent(Opts) ->
@@ -3961,7 +4024,7 @@ do_heavy_concurrent(Opts) ->
?line lists:foreach(fun (P) ->
M = erlang:monitor(process, P),
receive
- {'DOWN', Mon, process, P, _} ->
+ {'DOWN', M, process, P, _} ->
ok
end
end,
diff --git a/lib/stdlib/test/ms_transform_SUITE.erl b/lib/stdlib/test/ms_transform_SUITE.erl
index 79a0a9af89..2d90d5b823 100644
--- a/lib/stdlib/test/ms_transform_SUITE.erl
+++ b/lib/stdlib/test/ms_transform_SUITE.erl
@@ -37,6 +37,7 @@
-export([andalso_orelse/1]).
-export([float_1_function/1]).
-export([action_function/1]).
+-export([warnings/1]).
-export([init_per_testcase/2, fin_per_testcase/2]).
init_per_testcase(_Func, Config) ->
@@ -50,8 +51,90 @@ fin_per_testcase(_Func, Config) ->
all(suite) -> [from_shell,basic_ets,basic_dbg,records,record_index,multipass,
bitsyntax, record_defaults, andalso_orelse,
float_1_function, action_function,
+ warnings,
top_match, old_guards, autoimported, semicolon].
+%% This may be subject to change
+-define(WARN_NUMBER_SHADOW,50).
+warnings(suite) ->
+ [];
+warnings(doc) ->
+ ["Check that shadowed variables in fun head generate warning"];
+warnings(Config) when is_list(Config) ->
+ ?line setup(Config),
+ Prog = <<"A=5, "
+ "ets:fun2ms(fun({A,B}) "
+ " when is_integer(A) and (A+5 > B) -> "
+ " A andalso B "
+ " end)">>,
+ ?line [{_,[{_,ms_transform,{?WARN_NUMBER_SHADOW,'A'}}]}] =
+ compile_ww(Prog),
+ Prog2 = <<"C=5, "
+ "ets:fun2ms(fun({A,B} = C) "
+ " when is_integer(A) and (A+5 > B) -> "
+ " {A andalso B,C} "
+ " end)">>,
+ ?line [{_,[{_,ms_transform,{?WARN_NUMBER_SHADOW,'C'}}]}] =
+ compile_ww(Prog2),
+ Rec3 = <<"-record(a,{a,b,c,d=foppa}).">>,
+ Prog3 = <<"A=3,C=5, "
+ "ets:fun2ms(fun(#a{a = A, b = B} = C) "
+ " when is_integer(A) and (A+5 > B) -> "
+ " {A andalso B,C} "
+ " end)">>,
+ ?line [{_,[{_,ms_transform,{?WARN_NUMBER_SHADOW,'A'}},
+ {_,ms_transform,{?WARN_NUMBER_SHADOW,'C'}}]}] =
+ compile_ww(Rec3,Prog3),
+ Rec4 = <<"-record(a,{a,b,c,d=foppa}).">>,
+ Prog4 = <<"A=3,C=5, "
+ "F = fun(B) -> B*3 end,"
+ "erlang:display(F(A)),"
+ "ets:fun2ms(fun(#a{a = A, b = B} = C) "
+ " when is_integer(A) and (A+5 > B) -> "
+ " {A andalso B,C} "
+ " end)">>,
+ ?line [{_,[{_,ms_transform,{?WARN_NUMBER_SHADOW,'A'}},
+ {_,ms_transform,{?WARN_NUMBER_SHADOW,'C'}}]}] =
+ compile_ww(Rec4,Prog4),
+ Rec5 = <<"-record(a,{a,b,c,d=foppa}).">>,
+ Prog5 = <<"A=3,C=5, "
+ "F = fun(B) -> B*3 end,"
+ "erlang:display(F(A)),"
+ "B = ets:fun2ms(fun(#a{a = A, b = B} = C) "
+ " when is_integer(A) and (A+5 > B) -> "
+ " {A andalso B,C} "
+ " end)">>,
+ ?line [{_,[{_,ms_transform,{?WARN_NUMBER_SHADOW,'A'}},
+ {_,ms_transform,{?WARN_NUMBER_SHADOW,'C'}}]}] =
+ compile_ww(Rec5,Prog5),
+ Prog6 = <<" X=bar, "
+ " A = case X of"
+ " foo ->"
+ " foo;"
+ " Y ->"
+ " ets:fun2ms(fun(Y) ->" % This is a warning
+ " 3*Y"
+ " end)"
+ " end,"
+ " ets:fun2ms(fun(Y) ->" % Y out of "scope" here, so no warning
+ " {3*Y,A}"
+ " end)">>,
+ ?line [{_,[{_,ms_transform,{?WARN_NUMBER_SHADOW,'Y'}}]}] =
+ compile_ww(Prog6),
+ Prog7 = <<" X=bar, "
+ " A = case X of"
+ " foo ->"
+ " Y = foo;"
+ " Y ->"
+ " bar"
+ " end,"
+ " ets:fun2ms(fun(Y) ->" % Y exported from case and safe, so warn
+ " {3*Y,A}"
+ " end)">>,
+ ?line [{_,[{_,ms_transform,{?WARN_NUMBER_SHADOW,'Y'}}]}] =
+ compile_ww(Prog7),
+ ok.
+
andalso_orelse(suite) ->
[];
andalso_orelse(doc) ->
@@ -721,6 +804,24 @@ compile_and_run(Records,Expr) ->
code:load_binary(tmp,FN,Bin),
tmp:tmp().
+compile_ww(Expr) ->
+ compile_ww(<<>>,Expr).
+compile_ww(Records,Expr) ->
+ Prog = <<
+ "-module(tmp).\n",
+ "-include_lib(\"stdlib/include/ms_transform.hrl\").\n",
+ "-export([tmp/0]).\n",
+ Records/binary,"\n",
+ "tmp() ->\n",
+ Expr/binary,".\n">>,
+ FN=temp_name(),
+ file:write_file(FN,Prog),
+ {ok,Forms} = epp:parse_file(FN,"",""),
+ {ok,tmp,_Bin,Wlist} = compile:forms(Forms,[return_warnings,
+ nowarn_unused_vars,
+ nowarn_unused_record]),
+ Wlist.
+
do_eval(String) ->
{done,{ok,T,_},[]} = erl_scan:tokens(
[],
diff --git a/lib/stdlib/test/string_SUITE.erl b/lib/stdlib/test/string_SUITE.erl
index 3171b87c44..452e048dd7 100644
--- a/lib/stdlib/test/string_SUITE.erl
+++ b/lib/stdlib/test/string_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -240,7 +240,8 @@ copies(Config) when is_list(Config) ->
?line "." = string:copies(".", 1),
?line 30 = length(string:copies("123", 10)),
%% invalid arg type
- ?line {'EXIT',_} = (catch string:chars("hej", -1)),
+ ?line {'EXIT',_} = (catch string:copies("hej", -1)),
+ ?line {'EXIT',_} = (catch string:copies("hej", 2.0)),
ok.
words(suite) ->
diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk
index 02ea6d9d68..db7954af04 100644
--- a/lib/stdlib/vsn.mk
+++ b/lib/stdlib/vsn.mk
@@ -1,20 +1 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2010. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-#
-
-STDLIB_VSN = 1.17.1
+STDLIB_VSN = 1.17.2
diff --git a/lib/syntax_tools/src/epp_dodger.erl b/lib/syntax_tools/src/epp_dodger.erl
index 6b0f2034f8..9f6f7d815e 100644
--- a/lib/syntax_tools/src/epp_dodger.erl
+++ b/lib/syntax_tools/src/epp_dodger.erl
@@ -809,6 +809,8 @@ tokens_to_string([{atom,_,A} | Ts]) ->
io_lib:write_atom(A) ++ " " ++ tokens_to_string(Ts);
tokens_to_string([{string, _, S} | Ts]) ->
io_lib:write_string(S) ++ " " ++ tokens_to_string(Ts);
+tokens_to_string([{char, _, C} | Ts]) ->
+ io_lib:write_char(C) ++ " " ++ tokens_to_string(Ts);
tokens_to_string([{float, _, F} | Ts]) ->
float_to_list(F) ++ " " ++ tokens_to_string(Ts);
tokens_to_string([{integer, _, N} | Ts]) ->
diff --git a/lib/syntax_tools/src/erl_prettypr.erl b/lib/syntax_tools/src/erl_prettypr.erl
index c2c72d1ed2..7caf0b3db6 100644
--- a/lib/syntax_tools/src/erl_prettypr.erl
+++ b/lib/syntax_tools/src/erl_prettypr.erl
@@ -50,11 +50,15 @@
-type hook() :: 'none'
| fun((erl_syntax:syntaxTree(), _, _) -> prettypr:document()).
+-type clause_t() :: 'case_expr' | 'cond_expr' | 'fun_expr'
+ | 'if_expr' | 'receive_expr' | 'try_expr'
+ | {'function', prettypr:document()}
+ | {'rule', prettypr:document()}.
-record(ctxt, {prec = 0 :: integer(),
sub_indent = 2 :: non_neg_integer(),
break_indent = 4 :: non_neg_integer(),
- clause = undefined,
+ clause = undefined :: clause_t() | 'undefined',
hook = ?NOHOOK :: hook(),
paper = ?PAPER :: integer(),
ribbon = ?RIBBON :: integer(),
@@ -599,9 +603,8 @@ lay_2(Node, Ctxt) ->
case_expr ->
Ctxt1 = reset_prec(Ctxt),
D1 = lay(erl_syntax:case_expr_argument(Node), Ctxt1),
- D2 = lay_clauses(
- erl_syntax:case_expr_clauses(Node),
- case_expr, Ctxt1),
+ D2 = lay_clauses(erl_syntax:case_expr_clauses(Node),
+ case_expr, Ctxt1),
sep([par([follow(text("case"), D1, Ctxt1#ctxt.sub_indent),
text("of")],
Ctxt1#ctxt.break_indent),
@@ -819,9 +822,8 @@ lay_2(Node, Ctxt) ->
receive_expr ->
Ctxt1 = reset_prec(Ctxt),
- D1 = lay_clauses(
- erl_syntax:receive_expr_clauses(Node),
- receive_expr, Ctxt1),
+ D1 = lay_clauses(erl_syntax:receive_expr_clauses(Node),
+ receive_expr, Ctxt1),
D2 = case erl_syntax:receive_expr_timeout(Node) of
none ->
D1;
diff --git a/lib/syntax_tools/src/erl_recomment.erl b/lib/syntax_tools/src/erl_recomment.erl
index 94e760dad7..919e9cfc5d 100644
--- a/lib/syntax_tools/src/erl_recomment.erl
+++ b/lib/syntax_tools/src/erl_recomment.erl
@@ -215,7 +215,8 @@ comment_delta(Text) ->
%% the source file itself, but have been included by preprocessing. This
%% way, comments will not be inserted into such parts by mistake.
--record(filter, {file = undefined, line = 0 :: integer()}).
+-record(filter, {file = undefined :: file:filename() | 'undefined',
+ line = 0 :: integer()}).
filter_forms(Fs) ->
filter_forms(Fs, false, #filter{}).
@@ -721,8 +722,6 @@ tree_node_attrs(#tree{attrs = Attrs}) ->
%% =====================================================================
%% General utility functions
-%% Just the generic "maximum" function
-
%% Return the least positive integer of X and Y, or zero if none of them
%% are positive. (This is necessary for computing minimum source line
%% numbers, since zero (or negative) numbers may occur, but they
diff --git a/lib/syntax_tools/src/erl_syntax.erl b/lib/syntax_tools/src/erl_syntax.erl
index a40bf83c5a..9df5f26454 100644
--- a/lib/syntax_tools/src/erl_syntax.erl
+++ b/lib/syntax_tools/src/erl_syntax.erl
@@ -1818,7 +1818,7 @@ char_value(Node) ->
%%
%% @see char/1
--spec char_literal(syntaxTree()) -> string().
+-spec char_literal(syntaxTree()) -> nonempty_string().
char_literal(Node) ->
io_lib:write_char(char_value(Node)).
@@ -1908,7 +1908,7 @@ string_value(Node) ->
%%
%% @see string/1
--spec string_literal(syntaxTree()) -> string().
+-spec string_literal(syntaxTree()) -> nonempty_string().
string_literal(Node) ->
io_lib:write_string(string_value(Node)).
diff --git a/lib/syntax_tools/src/erl_syntax_lib.erl b/lib/syntax_tools/src/erl_syntax_lib.erl
index 4808971a59..97dfbfd7cd 100644
--- a/lib/syntax_tools/src/erl_syntax_lib.erl
+++ b/lib/syntax_tools/src/erl_syntax_lib.erl
@@ -49,10 +49,6 @@
-export_type([info_pair/0]).
%% =====================================================================
-
--type ordset(X) :: [X]. % XXX: TAKE ME OUT
-
-%% =====================================================================
%% @spec map(Function, Tree::syntaxTree()) -> syntaxTree()
%%
%% Function = (syntaxTree()) -> syntaxTree()
@@ -480,7 +476,7 @@ new_variable_names(0, Names, _, _, _) ->
%% @see annotate_bindings/1
%% @see //stdlib/ordsets
--spec annotate_bindings(erl_syntax:syntaxTree(), ordset(atom())) ->
+-spec annotate_bindings(erl_syntax:syntaxTree(), ordsets:ordset(atom())) ->
erl_syntax:syntaxTree().
annotate_bindings(Tree, Env) ->
@@ -1134,21 +1130,21 @@ collect_attribute(_, {N, V}, Info) ->
%% Abstract datatype for collecting module information.
--record(forms, {module, exports, module_imports, imports, attributes,
- records, errors, warnings, functions, rules}).
+-record(forms, {module = none :: 'none' | {'value', atom()},
+ exports = [] :: [{atom(), arity()}],
+ module_imports = [] :: [atom()],
+ imports = [] :: [{atom(), [{atom(), arity()}]}],
+ attributes = [] :: [{atom(), term()}],
+ records = [] :: [{atom(), [{atom(), field_default()}]}],
+ errors = [] :: [term()],
+ warnings = [] :: [term()],
+ functions = [] :: [{atom(), arity()}],
+ rules = [] :: [{atom(), arity()}]}).
+
+-type field_default() :: 'none' | erl_syntax:syntaxTree().
new_finfo() ->
- #forms{module = none,
- exports = [],
- module_imports = [],
- imports = [],
- attributes = [],
- records = [],
- errors = [],
- warnings = [],
- functions = [],
- rules = []
- }.
+ #forms{}.
finfo_set_module(Name, Info) ->
case Info#forms.module of
diff --git a/lib/syntax_tools/src/erl_tidy.erl b/lib/syntax_tools/src/erl_tidy.erl
index 021ab18736..1cfdc7234a 100644
--- a/lib/syntax_tools/src/erl_tidy.erl
+++ b/lib/syntax_tools/src/erl_tidy.erl
@@ -935,12 +935,13 @@ hidden_uses_2(Tree, Used) ->
Used
end.
+-type fa() :: {atom(), arity()}.
-type context() :: 'guard_expr' | 'guard_test' | 'normal'.
-record(env, {file :: file:filename(),
- module,
- current,
- imports,
+ module :: atom(),
+ current :: fa(),
+ imports = dict:new() :: dict(),
context = normal :: context(),
verbosity = 1 :: 0 | 1 | 2,
quiet = false :: boolean(),
@@ -951,7 +952,13 @@ hidden_uses_2(Tree, Used) ->
new_guard_tests = true :: boolean(),
old_guard_tests = false :: boolean()}).
--record(st, {varc, used, imported, vars, functions, new_forms, rename}).
+-record(st, {varc :: non_neg_integer(),
+ used = sets:new() :: set(),
+ imported :: set(),
+ vars :: set(),
+ functions :: set(),
+ new_forms = [] :: [erl_syntax:syntaxTree()],
+ rename :: dict()}).
visit_used(Names, Defs, Roots, Imports, Module, Opts) ->
File = proplists:get_value(file, Opts, ""),
diff --git a/lib/syntax_tools/src/igor.erl b/lib/syntax_tools/src/igor.erl
index 702b399615..aa933eb54b 100644
--- a/lib/syntax_tools/src/igor.erl
+++ b/lib/syntax_tools/src/igor.erl
@@ -119,20 +119,16 @@
%% =====================================================================
--type ordset(X) :: [X]. % XXX: TAKE ME OUT
-
-%% =====================================================================
-
%% Data structure for module information
-record(module, {name :: atom(),
vars = none :: [atom()] | 'none',
- functions :: ordset({atom(), arity()}),
- exports :: ordset({atom(), arity()})
- | ordset({{atom(), arity()}, term()}),
- aliases :: ordset({{atom(), arity()},
- {atom(), {atom(), arity()}}}),
- attributes :: ordset({atom(), term()}),
+ functions :: ordsets:ordset({atom(), arity()}),
+ exports :: ordsets:ordset({atom(), arity()})
+ | ordsets:ordset({{atom(), arity()}, term()}),
+ aliases :: ordsets:ordset({{atom(), arity()},
+ {atom(), {atom(), arity()}}}),
+ attributes :: ordsets:ordset({atom(), term()}),
records :: [{atom(), [{atom(), term()}]}]
}).
@@ -149,7 +145,7 @@ default_printer(Tree, Options) ->
-type moduleName() :: atom().
-type functionName() :: {atom(), arity()}.
-type functionPair() :: {functionName(), {moduleName(), functionName()}}.
--type stubDescriptor() :: [{moduleName(), [functionPair()], [attribute()]}].
+-type stubDescriptor() :: {moduleName(), [functionPair()], [attribute()]}.
-type notes() :: 'always' | 'yes' | 'no'.
@@ -209,7 +205,7 @@ parse_transform(Forms, Options) ->
%% @spec merge(Name::atom(), Files::[filename()]) -> [filename()]
%% @equiv merge(Name, Files, [])
--spec merge(atom(), [file:filename()]) -> [file:filename()].
+-spec merge(atom(), [file:filename()]) -> [file:filename(),...].
merge(Name, Files) ->
merge(Name, Files, []).
@@ -343,7 +339,7 @@ merge(Name, Files) ->
{suffix, ?DEFAULT_SUFFIX},
{verbose, false}]).
--spec merge(atom(), [file:filename()], [option()]) -> [file:filename()].
+-spec merge(atom(), [file:filename()], [option()]) -> [file:filename(),...].
merge(Name, Files, Opts) ->
Opts1 = Opts ++ ?DEFAULT_MERGE_OPTS,
@@ -484,7 +480,7 @@ merge_files(Name, Trees, Files, Opts) ->
%%
%% Forms = syntaxTree() | [syntaxTree()]
%%
-%% @type stubDescriptor() = [{ModuleName, Functions, [Attribute]}]
+%% @type stubDescriptor() = {ModuleName, Functions, [Attribute]}
%% ModuleName = atom()
%% Functions = [{FunctionName, {ModuleName, FunctionName}}]
%% FunctionName = {atom(), integer()}
@@ -687,15 +683,15 @@ merge_files(Name, Trees, Files, Opts) ->
%% Data structure for merging environment.
-record(merge, {target :: atom(),
- sources :: ordset(atom()),
- export :: ordset(atom()),
- static :: ordset(atom()),
- safe :: ordset(atom()),
+ sources :: ordsets:ordset(atom()),
+ export :: ordsets:ordset(atom()),
+ static :: ordsets:ordset(atom()),
+ safe :: ordsets:ordset(atom()),
preserved :: boolean(),
no_headers :: boolean(),
notes :: notes(),
redirect :: dict(), % = dict(atom(), atom())
- no_imports :: ordset(atom()),
+ no_imports :: ordsets:ordset(atom()),
options :: [option()]
}).
@@ -1035,7 +1031,12 @@ make_stub(M, Map, Env) ->
%% Removing and/or out-commenting program forms. The returned form
%% sequence tree is not necessarily flat.
--record(filter, {records :: set(), file_attributes, attributes}).
+-type atts() :: 'delete' | 'kill'.
+-type file_atts() :: 'delete' | 'keep' | 'kill'.
+
+-record(filter, {records :: set(),
+ file_attributes :: file_atts(),
+ attributes :: atts()}).
filter_forms(Tree, Env) ->
Forms = erl_syntax:form_list_elements(
@@ -1576,6 +1577,8 @@ alias_expansions_2(Modules, Table) ->
%% ---------------------------------------------------------------------
%% Merging the source code.
+-type map_fun() :: fun(({atom(), integer()}) -> {atom(), integer()}).
+
%% Data structure for code transformation environment.
-record(code, {module :: atom(),
@@ -1586,11 +1589,10 @@ alias_expansions_2(Modules, Table) ->
preserved :: boolean(),
no_headers :: boolean(),
notes :: notes(),
- map, % = ({atom(), int()}) -> {atom(), int()}
- renaming, % = (atom()) -> ({atom(), int()}) ->
- % {atom(), int()}
- expand :: dict(), % = dict({atom(), int()},
- % {atom(), {atom(), int()}})
+ map :: map_fun(),
+ renaming :: fun((atom()) -> map_fun()),
+ expand :: dict(), % = dict({atom(), integer()},
+ % {atom(), {atom(), integer()}})
redirect :: dict() % = dict(atom(), atom())
}).
diff --git a/lib/test_server/doc/src/notes.xml b/lib/test_server/doc/src/notes.xml
index dae071311c..e0c4c28e44 100644
--- a/lib/test_server/doc/src/notes.xml
+++ b/lib/test_server/doc/src/notes.xml
@@ -32,6 +32,48 @@
<file>notes.xml</file>
</header>
+<section><title>Test_Server 3.4.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Returning {return_group_result,failed} from end_per_group
+ in a group that is part of a sequence, did not cause the
+ proceeding cases (or groups) to get skipped. This has
+ been fixed.</p>
+ <p>
+ Own Id: OTP-8753 Aux Id: seq11644 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Common Test has been updated to handle start options and
+ test specification terms for test case groups (and test
+ cases in groups). Also, an option named 'label', has been
+ added that associates the test run with a name that
+ Common Test prints in the overview HTML logs.</p>
+ <p>
+ Own Id: OTP-8725 Aux Id: OTP-8727 </p>
+ </item>
+ <item>
+ <p>
+ It is now possible to skip all tests in a suite, or a
+ group, by returning {fail,Reason} from the end_tc/5
+ framework function for init_per_suite, or init_per_group.</p>
+ <p>
+ Own Id: OTP-8805 Aux Id: seq11664 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Test_Server 3.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/test_server/src/Makefile b/lib/test_server/src/Makefile
index d55a3a597d..3dca55178d 100644
--- a/lib/test_server/src/Makefile
+++ b/lib/test_server/src/Makefile
@@ -139,7 +139,7 @@ release_tests_spec: opt
$(TARGET_FILES) $(TS_TARGET_FILES) \
$(AUTOCONF_FILES) $(C_FILES) $(COVER_FILES) $(CONFIG) \
$(RELEASE_PATH)/test_server
- $(INSTALL_PROGRAM) $(PROGRAMS) $(RELEASE_PATH)/test_server
+ $(INSTALL_SCRIPT) $(PROGRAMS) $(RELEASE_PATH)/test_server
release_docs_spec:
diff --git a/lib/test_server/src/test_server.erl b/lib/test_server/src/test_server.erl
index acc9dbaab8..ee121e5bb6 100644
--- a/lib/test_server/src/test_server.erl
+++ b/lib/test_server/src/test_server.erl
@@ -1198,8 +1198,13 @@ process_return_val([Return], M,F,A, Loc, Final) when is_list(Return) ->
true -> % must be return value from end conf case
process_return_val1(Return, M,F,A, Loc, Final, []);
false -> % must be Config value from init conf case
- test_server_sup:framework_call(end_tc, [?pl2a(M),F,{ok,A}]),
- {Return,[]}
+ case test_server_sup:framework_call(end_tc, [?pl2a(M),F,{ok,A}]) of
+ {fail,FWReason} ->
+ fw_error_notify(M,F,A, FWReason),
+ {{failed,FWReason},[]};
+ _ ->
+ {Return,[]}
+ end
end;
%% the return value is not a list, so it's the return value from an
%% end conf case or it's a dummy value that can be ignored
diff --git a/lib/test_server/src/test_server_ctrl.erl b/lib/test_server/src/test_server_ctrl.erl
index 72f274d63a..1dc5646184 100644
--- a/lib/test_server/src/test_server_ctrl.erl
+++ b/lib/test_server/src/test_server_ctrl.erl
@@ -2269,13 +2269,14 @@ maybe_get_privdir() ->
run_test_cases_loop([{auto_skip_case,{Type,Ref,Case,Comment},SkipMode}|Cases],
Config, TimetrapData, Mode, Status) when Type==conf;
Type==make ->
-
file:set_cwd(filename:dirname(get(test_server_dir))),
CurrIOHandler = get(test_server_common_io_handler),
+ ParentMode = tl(Mode),
+
%% check and update the mode for test case execution and io msg handling
case {curr_ref(Mode),check_props(parallel, Mode)} of
{Ref,Ref} ->
- case check_props(parallel, tl(Mode)) of
+ case check_props(parallel, ParentMode) of
false ->
%% this is a skipped end conf for a top level parallel group,
%% buffered io can be flushed
@@ -2283,7 +2284,7 @@ run_test_cases_loop([{auto_skip_case,{Type,Ref,Case,Comment},SkipMode}|Cases],
set_io_buffering(undefined),
{Mod,Func} = skip_case(auto, Ref, 0, Case, Comment, false, SkipMode),
test_server_sup:framework_call(report, [tc_auto_skip,{?pl2a(Mod),Func,Comment}]),
- run_test_cases_loop(Cases, Config, TimetrapData, tl(Mode),
+ run_test_cases_loop(Cases, Config, TimetrapData, ParentMode,
delete_status(Ref, Status));
_ ->
%% this is a skipped end conf for a parallel group nested under a
@@ -2300,7 +2301,7 @@ run_test_cases_loop([{auto_skip_case,{Type,Ref,Case,Comment},SkipMode}|Cases],
_ ->
ok
end,
- run_test_cases_loop(Cases, Config, TimetrapData, tl(Mode),
+ run_test_cases_loop(Cases, Config, TimetrapData, ParentMode,
delete_status(Ref, Status))
end;
{Ref,false} ->
@@ -2308,7 +2309,31 @@ run_test_cases_loop([{auto_skip_case,{Type,Ref,Case,Comment},SkipMode}|Cases],
%% nested under a parallel group
{Mod,Func} = skip_case(auto, Ref, 0, Case, Comment, false, SkipMode),
test_server_sup:framework_call(report, [tc_auto_skip,{?pl2a(Mod),Func,Comment}]),
- run_test_cases_loop(Cases, Config, TimetrapData, tl(Mode),
+
+ %% Check if this group is auto skipped because of error in the init conf.
+ %% If so, check if the parent group is a sequence, and if it is, skip
+ %% all proceeding tests in that group.
+ GrName = get_name(Mode),
+ Cases1 =
+ case get_tc_results(Status) of
+ {_,_,Fails} when length(Fails) > 0 ->
+ case lists:member({group_result,GrName}, Fails) of
+ true ->
+ case check_prop(sequence, ParentMode) of
+ false ->
+ Cases;
+ ParentRef ->
+ Reason = {group_result,GrName,failed},
+ skip_cases_upto(ParentRef, Cases,
+ Reason, tc, Mode)
+ end;
+ false ->
+ Cases
+ end;
+ _ ->
+ Cases
+ end,
+ run_test_cases_loop(Cases1, Config, TimetrapData, ParentMode,
delete_status(Ref, Status));
{Ref,_} ->
%% this is a skipped end conf for a non-parallel group nested under
@@ -2381,7 +2406,6 @@ run_test_cases_loop([{skip_case,{Case,Comment}}|Cases],
%% a start *or* end conf case, wrapping test cases or other conf cases
run_test_cases_loop([{conf,Ref,Props,{Mod,Func}}|_Cases]=Cs0,
Config, TimetrapData, Mode0, Status) ->
-
CurrIOHandler = get(test_server_common_io_handler),
%% check and update the mode for test case execution and io msg handling
{StartConf,Mode,IOHandler,ConfTime,Status1} =
@@ -2543,7 +2567,7 @@ run_test_cases_loop([{conf,Ref,Props,{Mod,Func}}|_Cases]=Cs0,
{true,EndStatus,RestCs,Fun};
{repeat_until_any_ok,_} ->
{RestCs,Fun} = case get_tc_results(Status1) of
- {Ok,_,_} when length(Ok) > 0 ->
+ {Ok,_,_Fails} when length(Ok) > 0 ->
{Cases1,ReportStop};
_ ->
{CopiedCases++Cases1,?void_fun}
@@ -2627,22 +2651,24 @@ run_test_cases_loop([{conf,Ref,Props,{Mod,Func}}|_Cases]=Cs0,
{_,Fail,_} when element(1,Fail) == 'EXIT';
element(1,Fail) == timetrap_timeout;
element(1,Fail) == failed ->
- {Cases2,Config1} =
+ {Cases2,Config1,Status3} =
if StartConf ->
ReportAbortRepeat(failed),
print(minor, "~n*** ~p failed.~n"
" Skipping all cases.", [Func]),
Reason = {failed,{Mod,Func,Fail}},
- {skip_cases_upto(Ref, Cases, Reason, conf, CurrMode),Config};
+ {skip_cases_upto(Ref, Cases, Reason, conf, CurrMode),
+ Config,
+ update_status(failed, group_result, get_name(Mode),
+ delete_status(Ref, Status2))};
not StartConf ->
ReportRepeatStop(),
print_conf_time(ConfTime),
- {Cases,tl(Config)}
+ {Cases,tl(Config),delete_status(Ref, Status2)}
end,
set_io_buffering(IOHandler),
stop_minor_log_file(),
- run_test_cases_loop(Cases2, Config1, TimetrapData, Mode,
- delete_status(Ref, Status2));
+ run_test_cases_loop(Cases2, Config1, TimetrapData, Mode, Status3);
{died,Why,_} when Func == init_per_suite ->
print(minor, "~n*** Unexpected exit during init_per_suite.~n", []),
Reason = {failed,{Mod,init_per_suite,Why}},
@@ -2686,22 +2712,38 @@ run_test_cases_loop([{conf,Ref,Props,{Mod,Func}}|_Cases]=Cs0,
Mode, Status2);
{_,_EndConfRetVal,Opts} ->
- %% check if return_group_result is set (ok, skipped or failed) and
- %% if so return the value to the group "above" so that result may be
- %% used for evaluating repeat_until_*
- Status3 =
+ %% Check if return_group_result is set (ok, skipped or failed) and
+ %% if so:
+ %% 1) *If* the parent group is a sequence, skip all proceeding tests
+ %% in that group.
+ %% 2) Return the value to the group "above" so that result may be
+ %% used for evaluating a 'repeat_until_*' property.
+ GrName = get_name(Mode0, Func),
+ {Cases2,Status3} =
case lists:keysearch(return_group_result, 1, Opts) of
+ {value,{_,failed}} ->
+ case {curr_ref(Mode),check_prop(sequence, Mode)} of
+ {ParentRef,ParentRef} ->
+ Reason = {group_result,GrName,failed},
+ {skip_cases_upto(ParentRef, Cases, Reason, tc, Mode),
+ update_status(failed, group_result, GrName,
+ delete_status(Ref, Status2))};
+ _ ->
+ {Cases,update_status(failed, group_result, GrName,
+ delete_status(Ref, Status2))}
+ end;
{value,{_,GroupResult}} ->
- update_status(GroupResult, group_result, Func,
- delete_status(Ref, Status2));
+ {Cases,update_status(GroupResult, group_result, GrName,
+ delete_status(Ref, Status2))};
false ->
- delete_status(Ref, Status2)
+ {Cases,update_status(ok, group_result, GrName,
+ delete_status(Ref, Status2))}
end,
print_conf_time(ConfTime),
ReportRepeatStop(),
set_io_buffering(IOHandler),
stop_minor_log_file(),
- run_test_cases_loop(Cases, tl(Config), TimetrapData, Mode, Status3)
+ run_test_cases_loop(Cases2, tl(Config), TimetrapData, Mode, Status3)
end;
run_test_cases_loop([{make,Ref,{Mod,Func,Args}}|Cases0], Config, TimetrapData, Mode, Status) ->
@@ -2835,7 +2877,10 @@ get_copied_cases([{_,{_,Cases}} | _Status]) ->
Cases.
get_tc_results([{_,{OkSkipFail,_}} | _Status]) ->
- OkSkipFail.
+ OkSkipFail;
+get_tc_results([]) -> % in case init_per_suite crashed
+ {[],[],[]}.
+
conf(Ref, Props) ->
{Ref,Props,?now}.
@@ -2870,6 +2915,12 @@ check_props(Attrib, Mode) ->
[Ref|_] -> Ref
end.
+get_name(Mode, Def) ->
+ case get_name(Mode) of
+ undefined -> Def;
+ Name -> Name
+ end.
+
get_name([{_Ref,Props,_}|_]) ->
proplists:get_value(name, Props);
get_name([]) ->
diff --git a/lib/test_server/src/ts_install.erl b/lib/test_server/src/ts_install.erl
index bbbb7883db..2ddffccf5b 100644
--- a/lib/test_server/src/ts_install.erl
+++ b/lib/test_server/src/ts_install.erl
@@ -226,9 +226,11 @@ to_upper(String) ->
String).
word_size() ->
- case erlang:system_info(wordsize) of
- 4 -> "";
- 8 -> "/64"
+ case {erlang:system_info({wordsize,external}),
+ erlang:system_info({wordsize,internal})} of
+ {4,4} -> "";
+ {8,8} -> "/64";
+ {8,4} -> "/Halfword"
end.
linux_dist() ->
diff --git a/lib/test_server/src/ts_lib.erl b/lib/test_server/src/ts_lib.erl
index c90f4e511b..2f0a4ea8c0 100644
--- a/lib/test_server/src/ts_lib.erl
+++ b/lib/test_server/src/ts_lib.erl
@@ -21,6 +21,8 @@
-include_lib("kernel/include/file.hrl").
-include("ts.hrl").
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([error/1, var/2, erlang_type/0,
initial_capital/1, interesting_logs/1,
specs/1, suites/2, last_test/1,
diff --git a/lib/test_server/src/ts_reports.erl b/lib/test_server/src/ts_reports.erl
index b41291d342..f981a77ae4 100644
--- a/lib/test_server/src/ts_reports.erl
+++ b/lib/test_server/src/ts_reports.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -27,6 +27,8 @@
-include_lib("kernel/include/file.hrl").
-include("ts.hrl").
+-compile({no_auto_import,[error/1]}).
+
-import(filename, [basename/1, rootname/1]).
-import(ts_lib, [error/1]).
diff --git a/lib/test_server/test/Makefile b/lib/test_server/test/Makefile
index 702d73f5af..fcb1282d16 100644
--- a/lib/test_server/test/Makefile
+++ b/lib/test_server/test/Makefile
@@ -88,7 +88,7 @@ release_spec: opt
release_tests_spec: make_emakefile
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) $(EMAKEFILE) $(ERL_FILES) $(COVERFILE) $(RELSYSDIR)
- $(INSTALL_PROGRAM) test_server.spec $(RELSYSDIR)
+ $(INSTALL_DATA) test_server.spec $(RELSYSDIR)
chmod -f -R u+w $(RELSYSDIR)
@tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
diff --git a/lib/tools/doc/src/erlang_mode.xml b/lib/tools/doc/src/erlang_mode.xml
index 912c442153..c21afc1f9b 100644
--- a/lib/tools/doc/src/erlang_mode.xml
+++ b/lib/tools/doc/src/erlang_mode.xml
@@ -173,7 +173,7 @@
sum(L) -> sum(L, 0).
sum([H|T], Sum) -> sum(T, Sum + H);
- sum([], Sum) -> Sum."</code>
+ sum([], Sum) -> Sum.</code>
</item>
</list>
</section>
diff --git a/lib/tools/doc/src/erlang_mode_chapter.xml b/lib/tools/doc/src/erlang_mode_chapter.xml
index b22c6b1809..8aabd6ae74 100644
--- a/lib/tools/doc/src/erlang_mode_chapter.xml
+++ b/lib/tools/doc/src/erlang_mode_chapter.xml
@@ -45,7 +45,7 @@
<section>
<title>Elisp</title>
- <p>There are two Elsip modules include in this tool package
+ <p>There are two Elisp modules included in this tool package
for Emacs. There is erlang.el that defines the actual erlang mode
and there is erlang-start.el that makes some nice initializations.</p>
</section>
diff --git a/lib/tools/doc/src/notes.xml b/lib/tools/doc/src/notes.xml
index b9e1ef2959..4a71993da9 100644
--- a/lib/tools/doc/src/notes.xml
+++ b/lib/tools/doc/src/notes.xml
@@ -30,6 +30,22 @@
</header>
<p>This document describes the changes made to the Tools application.</p>
+<section><title>Tools 2.6.6.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ <c>cover</c> will now show ampersand characters in the
+ source code correctly. (Thanks to Tom Moertel.)</p>
+ <p>
+ Own Id: OTP-8776</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Tools 2.6.6</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/tools/emacs/erlang.el b/lib/tools/emacs/erlang.el
index 91acfdf2b6..ed825a298f 100644
--- a/lib/tools/emacs/erlang.el
+++ b/lib/tools/emacs/erlang.el
@@ -1481,7 +1481,23 @@ Other commands:
erlang-font-lock-keywords-3
erlang-font-lock-keywords-4)
nil nil ((?_ . "w")) erlang-beginning-of-clause
- (font-lock-mark-block-function . erlang-mark-clause))))
+ (font-lock-mark-block-function . erlang-mark-clause)
+ (font-lock-syntactic-keywords
+ ;; A dollar sign right before the double quote that ends a
+ ;; string is not a character escape.
+ ;;
+ ;; And a "string" has with a double quote not escaped by a
+ ;; dollar sign, any number of non-backslash non-newline
+ ;; characters or escaped backslashes, a dollar sign
+ ;; (otherwise we wouldn't care) and a double quote. This
+ ;; doesn't match multi-line strings, but this is probably
+ ;; the best we can get, since while font-locking we don't
+ ;; know whether matching started inside a string: limiting
+ ;; search to a single line keeps things sane.
+ . (("\\(?:^\\|[^$]\\)\"\\(?:[^\"\n]\\|\\\\\"\\)*\\(\\$\\)\"" 1 "w")
+ ;; And the dollar sign in $\" escapes two characters, not
+ ;; just one.
+ ("\\(\\$\\)\\\\\\\"" 1 "'"))))))
diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl
index 6501e05a6e..c4d1bd1d2f 100644
--- a/lib/tools/src/cover.erl
+++ b/lib/tools/src/cover.erl
@@ -2174,6 +2174,8 @@ escape_lt_and_gt1([$<|T],Acc) ->
escape_lt_and_gt1(T,[$;,$t,$l,$&|Acc]);
escape_lt_and_gt1([$>|T],Acc) ->
escape_lt_and_gt1(T,[$;,$t,$g,$&|Acc]);
+escape_lt_and_gt1([$&|T],Acc) ->
+ escape_lt_and_gt1(T,[$;,$p,$m,$a,$&|Acc]);
escape_lt_and_gt1([],Acc) ->
lists:reverse(Acc);
escape_lt_and_gt1([H|T],Acc) ->
diff --git a/lib/tools/src/xref_base.erl b/lib/tools/src/xref_base.erl
index 1656899e8f..93f0e9c0c8 100644
--- a/lib/tools/src/xref_base.erl
+++ b/lib/tools/src/xref_base.erl
@@ -19,6 +19,8 @@
-module(xref_base).
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([new/0, new/1, delete/1,
add_directory/2, add_directory/3,
add_module/2, add_module/3,
diff --git a/lib/tools/src/xref_compiler.erl b/lib/tools/src/xref_compiler.erl
index c80eb0e669..1445e135be 100644
--- a/lib/tools/src/xref_compiler.erl
+++ b/lib/tools/src/xref_compiler.erl
@@ -31,6 +31,8 @@
-define(CALL(F), ok).
-endif.
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([compile/2]).
-export([update_graph_counter/3]).
diff --git a/lib/tools/src/xref_utils.erl b/lib/tools/src/xref_utils.erl
index 0ef199cec7..9d4a175d88 100644
--- a/lib/tools/src/xref_utils.erl
+++ b/lib/tools/src/xref_utils.erl
@@ -18,6 +18,8 @@
%%
-module(xref_utils).
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([xset/2]).
-export([is_directory/1, file_info/1, fa_to_mfa/2]).
diff --git a/lib/tools/vsn.mk b/lib/tools/vsn.mk
index abe9a804f0..77b5254eaa 100644
--- a/lib/tools/vsn.mk
+++ b/lib/tools/vsn.mk
@@ -1,19 +1 @@
-# This is an -*-makefile-*- file.
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2010. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-
-TOOLS_VSN = 2.6.6
+TOOLS_VSN = 2.6.6.1
diff --git a/lib/tv/doc/src/notes.xml b/lib/tv/doc/src/notes.xml
index 43b650dd29..388bb82c91 100644
--- a/lib/tv/doc/src/notes.xml
+++ b/lib/tv/doc/src/notes.xml
@@ -30,6 +30,23 @@
</header>
<p>This document describes the changes made to the TV application.</p>
+<section><title>TV 2.1.4.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ With some window managers (e.g. stumpwm), <c>tv</c> would
+ constantly restart while trying to open a table. (Thanks
+ to Dmitriy Budashny.)</p>
+ <p>
+ Own Id: OTP-8751</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>TV 2.1.4.5</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/tv/vsn.mk b/lib/tv/vsn.mk
index 93973489bc..958aa0ea42 100644
--- a/lib/tv/vsn.mk
+++ b/lib/tv/vsn.mk
@@ -1,20 +1 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2010. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-#
-
-TV_VSN = 2.1.4.5
+TV_VSN = 2.1.4.6
diff --git a/lib/typer/src/typer.erl b/lib/typer/src/typer.erl
index cebe6ea488..e19614f911 100644
--- a/lib/typer/src/typer.erl
+++ b/lib/typer/src/typer.erl
@@ -2,7 +2,7 @@
%%-----------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -26,6 +26,8 @@
-module(typer).
+%% Avoid warning for local function error/1 clashing with autoimported BIF.
+-compile({no_auto_import,[error/1]}).
-export([start/0]).
-export([error/1, compile_error/1]). % for error reporting
diff --git a/lib/typer/vsn.mk b/lib/typer/vsn.mk
index 285fa62da3..7f4aabb335 100644
--- a/lib/typer/vsn.mk
+++ b/lib/typer/vsn.mk
@@ -1 +1 @@
-TYPER_VSN = 0.1.7.4
+TYPER_VSN = 0.1.7.5
diff --git a/lib/wx/.gitignore b/lib/wx/.gitignore
new file mode 100644
index 0000000000..fd76f078d7
--- /dev/null
+++ b/lib/wx/.gitignore
@@ -0,0 +1,2 @@
+test_log_*
+wx_test_case_info
diff --git a/lib/wx/api_gen/wxapi.conf b/lib/wx/api_gen/wxapi.conf
index c91a9d7fff..6bafda5b9d 100644
--- a/lib/wx/api_gen/wxapi.conf
+++ b/lib/wx/api_gen/wxapi.conf
@@ -902,8 +902,8 @@
['wxTreeCtrl','~wxTreeCtrl','AddRoot','AppendItem',
%% Not on Windows 'AssignButtonsImageList','GetButtonsImageList','SetButtonsImageList'
'AssignImageList','AssignStateImageList','Collapse','CollapseAndReset',
- 'Create','Delete','DeleteAllItems','DeleteChildren',{'EditLabel',1},
- %'EndEditLabel',
+ 'Create','Delete','DeleteAllItems','DeleteChildren',
+ {'EditLabel', [{"textCtrlClass", [nowhere]}]}, %'EndEditLabel',
'EnsureVisible','Expand','GetBoundingRect',
'GetChildrenCount','GetCount','GetEditControl',
{'GetFirstChild',[{"cookie", out}]}, {'GetNextChild',[{"cookie", [both]}]},
@@ -1740,6 +1740,11 @@
%% 'GetItemRect', 'SetItemRect', 'GetToolId', 'SetToolId'
%% ]}.
+{class, wxSystemSettings, object, [],
+ [
+ 'GetColour','GetFont','GetMetric','GetScreenType'
+ ]}.
+
{class, wxAuiNotebookEvent, wxNotifyEvent,
[{acc, [{old_selection, "GetOldSelection()"},
{selection, "GetSelection()"},
diff --git a/lib/wx/c_src/gen/wxe_derived_dest.h b/lib/wx/c_src/gen/wxe_derived_dest.h
index 57b0faa2cb..ad46a98c90 100644
--- a/lib/wx/c_src/gen/wxe_derived_dest.h
+++ b/lib/wx/c_src/gen/wxe_derived_dest.h
@@ -736,7 +736,7 @@ void WxeApp::delete_object(void *ptr, wxeRefData *refd) {
case 211: /* delete (wxFileDataObject *) ptr;These objects must be deleted by owner object */ break;
case 212: /* delete (wxTextDataObject *) ptr;These objects must be deleted by owner object */ break;
case 213: /* delete (wxBitmapDataObject *) ptr;These objects must be deleted by owner object */ break;
- case 222: delete (wxLogNull *) ptr; break;
+ case 223: delete (wxLogNull *) ptr; break;
default: delete (wxObject *) ptr;
}}
diff --git a/lib/wx/c_src/gen/wxe_events.cpp b/lib/wx/c_src/gen/wxe_events.cpp
index a6857442c9..692eef858c 100644
--- a/lib/wx/c_src/gen/wxe_events.cpp
+++ b/lib/wx/c_src/gen/wxe_events.cpp
@@ -266,41 +266,41 @@ void initEventTable()
{wxEVT_COMMAND_SPLITTER_DOUBLECLICKED, 217, "command_splitter_doubleclicked"},
{wxEVT_COMMAND_SPLITTER_UNSPLIT, 217, "command_splitter_unsplit"},
{wxEVT_COMMAND_HTML_LINK_CLICKED, 219, "command_html_link_clicked"},
- {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, 220, "command_auinotebook_page_close"},
- {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, 220, "command_auinotebook_page_changed"},
- {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, 220, "command_auinotebook_page_changing"},
- {wxEVT_COMMAND_AUINOTEBOOK_BUTTON, 220, "command_auinotebook_button"},
- {wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, 220, "command_auinotebook_begin_drag"},
- {wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, 220, "command_auinotebook_end_drag"},
- {wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, 220, "command_auinotebook_drag_motion"},
- {wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND, 220, "command_auinotebook_allow_dnd"},
+ {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, 221, "command_auinotebook_page_close"},
+ {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, 221, "command_auinotebook_page_changed"},
+ {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, 221, "command_auinotebook_page_changing"},
+ {wxEVT_COMMAND_AUINOTEBOOK_BUTTON, 221, "command_auinotebook_button"},
+ {wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, 221, "command_auinotebook_begin_drag"},
+ {wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, 221, "command_auinotebook_end_drag"},
+ {wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, 221, "command_auinotebook_drag_motion"},
+ {wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND, 221, "command_auinotebook_allow_dnd"},
#if wxCHECK_VERSION(2,8,5)
- {wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN, 220, "command_auinotebook_tab_middle_down"},
+ {wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN, 221, "command_auinotebook_tab_middle_down"},
#endif
#if wxCHECK_VERSION(2,8,5)
- {wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP, 220, "command_auinotebook_tab_middle_up"},
+ {wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP, 221, "command_auinotebook_tab_middle_up"},
#endif
#if wxCHECK_VERSION(2,8,5)
- {wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN, 220, "command_auinotebook_tab_right_down"},
+ {wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN, 221, "command_auinotebook_tab_right_down"},
#endif
#if wxCHECK_VERSION(2,8,5)
- {wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP, 220, "command_auinotebook_tab_right_up"},
+ {wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP, 221, "command_auinotebook_tab_right_up"},
#endif
#if wxCHECK_VERSION(2,8,5)
- {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, 220, "command_auinotebook_page_closed"},
+ {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, 221, "command_auinotebook_page_closed"},
#endif
#if wxCHECK_VERSION(2,8,5)
- {wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE, 220, "command_auinotebook_drag_done"},
+ {wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE, 221, "command_auinotebook_drag_done"},
#endif
#if wxCHECK_VERSION(2,8,5)
- {wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK, 220, "command_auinotebook_bg_dclick"},
+ {wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK, 221, "command_auinotebook_bg_dclick"},
#endif
- {wxEVT_AUI_PANE_BUTTON, 221, "aui_pane_button"},
- {wxEVT_AUI_PANE_CLOSE, 221, "aui_pane_close"},
- {wxEVT_AUI_PANE_MAXIMIZE, 221, "aui_pane_maximize"},
- {wxEVT_AUI_PANE_RESTORE, 221, "aui_pane_restore"},
- {wxEVT_AUI_RENDER, 221, "aui_render"},
- {wxEVT_AUI_FIND_MANAGER, 221, "aui_find_manager"},
+ {wxEVT_AUI_PANE_BUTTON, 222, "aui_pane_button"},
+ {wxEVT_AUI_PANE_CLOSE, 222, "aui_pane_close"},
+ {wxEVT_AUI_PANE_MAXIMIZE, 222, "aui_pane_maximize"},
+ {wxEVT_AUI_PANE_RESTORE, 222, "aui_pane_restore"},
+ {wxEVT_AUI_RENDER, 222, "aui_render"},
+ {wxEVT_AUI_FIND_MANAGER, 222, "aui_find_manager"},
{-1, 0, }
};
for(int i=0; event_types[i].ev_type != -1; i++) {
@@ -778,7 +778,7 @@ case 219: {// wxHtmlLinkEvent
rt.addTupleCount(3);
break;
}
-case 220: {// wxAuiNotebookEvent
+case 221: {// wxAuiNotebookEvent
wxAuiNotebookEvent * ev = (wxAuiNotebookEvent *) event;
wxAuiNotebook * GetDragSource = ev->GetDragSource();
evClass = (char*)"wxAuiNotebookEvent";
@@ -790,7 +790,7 @@ case 220: {// wxAuiNotebookEvent
rt.addTupleCount(5);
break;
}
-case 221: {// wxAuiManagerEvent
+case 222: {// wxAuiManagerEvent
wxAuiManagerEvent * ev = (wxAuiManagerEvent *) event;
wxAuiManager * GetManager = ev->GetManager();
wxAuiPaneInfo * GetPane = ev->GetPane();
diff --git a/lib/wx/c_src/gen/wxe_funcs.cpp b/lib/wx/c_src/gen/wxe_funcs.cpp
index fd496c2ccc..8c056bbb91 100644
--- a/lib/wx/c_src/gen/wxe_funcs.cpp
+++ b/lib/wx/c_src/gen/wxe_funcs.cpp
@@ -18501,6 +18501,15 @@ case wxTreeCtrl_DeleteChildren: { // wxTreeCtrl::DeleteChildren
This->DeleteChildren(item);
break;
}
+case wxTreeCtrl_EditLabel: { // wxTreeCtrl::EditLabel
+ wxTreeCtrl *This = (wxTreeCtrl *) getPtr(bp,memenv); bp += 4;
+ bp += 4; /* Align */
+ wxTreeItemId item = wxTreeItemId((void *) *(wxUint64 *) bp); bp += 8;
+ if(!This) throw wxe_badarg(0);
+ wxTextCtrl * Result = (wxTextCtrl*)This->EditLabel(item);
+ rt.addRef(getRef((void *)Result,memenv), "wxTextCtrl");
+ break;
+}
case wxTreeCtrl_EnsureVisible: { // wxTreeCtrl::EnsureVisible
wxTreeCtrl *This = (wxTreeCtrl *) getPtr(bp,memenv); bp += 4;
bp += 4; /* Align */
@@ -30976,6 +30985,36 @@ case wxHtmlLinkEvent_GetLinkInfo: { // wxHtmlLinkEvent::GetLinkInfo
rt.add(Result);
break;
}
+case wxSystemSettings_GetColour: { // wxSystemSettings::GetColour
+ wxSystemColour index = *(wxSystemColour *) bp; bp += 4;;
+ wxColour Result = wxSystemSettings::GetColour((wxSystemColour) index);
+ rt.add(Result);
+ break;
+}
+case wxSystemSettings_GetFont: { // wxSystemSettings::GetFont
+ wxSystemFont index = *(wxSystemFont *) bp; bp += 4;;
+ wxFont * Result = new wxFont(wxSystemSettings::GetFont((wxSystemFont) index)); newPtr((void *) Result,3, memenv);;
+ rt.addRef(getRef((void *)Result,memenv), "wxFont");
+ break;
+}
+case wxSystemSettings_GetMetric: { // wxSystemSettings::GetMetric
+ wxWindow * win=NULL;
+ wxSystemMetric index = *(wxSystemMetric *) bp; bp += 4;;
+ bp += 4; /* Align */
+ while( * (int*) bp) { switch (* (int*) bp) {
+ case 1: {bp += 4;
+win = (wxWindow *) getPtr(bp,memenv); bp += 4;
+ } break;
+ }};
+ int Result = wxSystemSettings::GetMetric((wxSystemMetric) index,win);
+ rt.addInt(Result);
+ break;
+}
+case wxSystemSettings_GetScreenType: { // wxSystemSettings::GetScreenType
+ int Result = wxSystemSettings::GetScreenType();
+ rt.addInt(Result);
+ break;
+}
case wxAuiNotebookEvent_SetSelection: { // wxAuiNotebookEvent::SetSelection
wxAuiNotebookEvent *This = (wxAuiNotebookEvent *) getPtr(bp,memenv); bp += 4;
int * s = (int *) bp; bp += 4;
@@ -31110,7 +31149,7 @@ case wxAuiManagerEvent_CanVeto: { // wxAuiManagerEvent::CanVeto
}
case wxLogNull_new: { // wxLogNull::wxLogNull
wxLogNull * Result = new wxLogNull();
- newPtr((void *) Result, 222, memenv);
+ newPtr((void *) Result, 223, memenv);
rt.addRef(getRef((void *)Result,memenv), "wxLogNull");
break;
}
diff --git a/lib/wx/c_src/gen/wxe_macros.h b/lib/wx/c_src/gen/wxe_macros.h
index 415b7f0b29..4fb76f960b 100644
--- a/lib/wx/c_src/gen/wxe_macros.h
+++ b/lib/wx/c_src/gen/wxe_macros.h
@@ -1882,1444 +1882,1449 @@
#define wxTreeCtrl_Delete 2007
#define wxTreeCtrl_DeleteAllItems 2008
#define wxTreeCtrl_DeleteChildren 2009
-#define wxTreeCtrl_EnsureVisible 2010
-#define wxTreeCtrl_Expand 2011
-#define wxTreeCtrl_GetBoundingRect 2012
-#define wxTreeCtrl_GetChildrenCount 2014
-#define wxTreeCtrl_GetCount 2015
-#define wxTreeCtrl_GetEditControl 2016
-#define wxTreeCtrl_GetFirstChild 2017
-#define wxTreeCtrl_GetNextChild 2018
-#define wxTreeCtrl_GetFirstVisibleItem 2019
-#define wxTreeCtrl_GetImageList 2020
-#define wxTreeCtrl_GetIndent 2021
-#define wxTreeCtrl_GetItemBackgroundColour 2022
-#define wxTreeCtrl_GetItemData 2023
-#define wxTreeCtrl_GetItemFont 2024
-#define wxTreeCtrl_GetItemImage_1 2025
-#define wxTreeCtrl_GetItemImage_2 2026
-#define wxTreeCtrl_GetItemText 2027
-#define wxTreeCtrl_GetItemTextColour 2028
-#define wxTreeCtrl_GetLastChild 2029
-#define wxTreeCtrl_GetNextSibling 2030
-#define wxTreeCtrl_GetNextVisible 2031
-#define wxTreeCtrl_GetItemParent 2032
-#define wxTreeCtrl_GetPrevSibling 2033
-#define wxTreeCtrl_GetPrevVisible 2034
-#define wxTreeCtrl_GetRootItem 2035
-#define wxTreeCtrl_GetSelection 2036
-#define wxTreeCtrl_GetSelections 2037
-#define wxTreeCtrl_GetStateImageList 2038
-#define wxTreeCtrl_HitTest 2039
-#define wxTreeCtrl_InsertItem 2041
-#define wxTreeCtrl_IsBold 2042
-#define wxTreeCtrl_IsExpanded 2043
-#define wxTreeCtrl_IsSelected 2044
-#define wxTreeCtrl_IsVisible 2045
-#define wxTreeCtrl_ItemHasChildren 2046
-#define wxTreeCtrl_PrependItem 2047
-#define wxTreeCtrl_ScrollTo 2048
-#define wxTreeCtrl_SelectItem_1 2049
-#define wxTreeCtrl_SelectItem_2 2050
-#define wxTreeCtrl_SetIndent 2051
-#define wxTreeCtrl_SetImageList 2052
-#define wxTreeCtrl_SetItemBackgroundColour 2053
-#define wxTreeCtrl_SetItemBold 2054
-#define wxTreeCtrl_SetItemData 2055
-#define wxTreeCtrl_SetItemDropHighlight 2056
-#define wxTreeCtrl_SetItemFont 2057
-#define wxTreeCtrl_SetItemHasChildren 2058
-#define wxTreeCtrl_SetItemImage_2 2059
-#define wxTreeCtrl_SetItemImage_3 2060
-#define wxTreeCtrl_SetItemText 2061
-#define wxTreeCtrl_SetItemTextColour 2062
-#define wxTreeCtrl_SetStateImageList 2063
-#define wxTreeCtrl_SetWindowStyle 2064
-#define wxTreeCtrl_SortChildren 2065
-#define wxTreeCtrl_Toggle 2066
-#define wxTreeCtrl_ToggleItemSelection 2067
-#define wxTreeCtrl_Unselect 2068
-#define wxTreeCtrl_UnselectAll 2069
-#define wxTreeCtrl_UnselectItem 2070
-#define wxScrollBar_new_0 2071
-#define wxScrollBar_new_3 2072
-#define wxScrollBar_destruct 2073
-#define wxScrollBar_Create 2074
-#define wxScrollBar_GetRange 2075
-#define wxScrollBar_GetPageSize 2076
-#define wxScrollBar_GetThumbPosition 2077
-#define wxScrollBar_GetThumbSize 2078
-#define wxScrollBar_SetThumbPosition 2079
-#define wxScrollBar_SetScrollbar 2080
-#define wxSpinButton_new_2 2082
-#define wxSpinButton_new_0 2083
-#define wxSpinButton_Create 2084
-#define wxSpinButton_GetMax 2085
-#define wxSpinButton_GetMin 2086
-#define wxSpinButton_GetValue 2087
-#define wxSpinButton_SetRange 2088
-#define wxSpinButton_SetValue 2089
-#define wxSpinButton_destroy 2090
-#define wxSpinCtrl_new_0 2091
-#define wxSpinCtrl_new_2 2092
-#define wxSpinCtrl_Create 2094
-#define wxSpinCtrl_SetValue_1_1 2097
-#define wxSpinCtrl_SetValue_1_0 2098
-#define wxSpinCtrl_GetValue 2100
-#define wxSpinCtrl_SetRange 2102
-#define wxSpinCtrl_SetSelection 2103
-#define wxSpinCtrl_GetMin 2105
-#define wxSpinCtrl_GetMax 2107
-#define wxSpinCtrl_destroy 2108
-#define wxStaticText_new_0 2109
-#define wxStaticText_new_4 2110
-#define wxStaticText_Create 2111
-#define wxStaticText_GetLabel 2112
-#define wxStaticText_SetLabel 2113
-#define wxStaticText_Wrap 2114
-#define wxStaticText_destroy 2115
-#define wxStaticBitmap_new_0 2116
-#define wxStaticBitmap_new_4 2117
-#define wxStaticBitmap_Create 2118
-#define wxStaticBitmap_GetBitmap 2119
-#define wxStaticBitmap_SetBitmap 2120
-#define wxStaticBitmap_destroy 2121
-#define wxRadioBox_new 2122
-#define wxRadioBox_destruct 2124
-#define wxRadioBox_Create 2125
-#define wxRadioBox_Enable_2 2126
-#define wxRadioBox_Enable_1 2127
-#define wxRadioBox_GetSelection 2128
-#define wxRadioBox_GetString 2129
-#define wxRadioBox_SetSelection 2130
-#define wxRadioBox_Show_2 2131
-#define wxRadioBox_Show_1 2132
-#define wxRadioBox_GetColumnCount 2133
-#define wxRadioBox_GetItemHelpText 2134
-#define wxRadioBox_GetItemToolTip 2135
-#define wxRadioBox_GetItemFromPoint 2137
-#define wxRadioBox_GetRowCount 2138
-#define wxRadioBox_IsItemEnabled 2139
-#define wxRadioBox_IsItemShown 2140
-#define wxRadioBox_SetItemHelpText 2141
-#define wxRadioBox_SetItemToolTip 2142
-#define wxRadioButton_new_0 2143
-#define wxRadioButton_new_4 2144
-#define wxRadioButton_Create 2145
-#define wxRadioButton_GetValue 2146
-#define wxRadioButton_SetValue 2147
-#define wxRadioButton_destroy 2148
-#define wxSlider_new_6 2150
-#define wxSlider_new_0 2151
-#define wxSlider_Create 2152
-#define wxSlider_GetLineSize 2153
-#define wxSlider_GetMax 2154
-#define wxSlider_GetMin 2155
-#define wxSlider_GetPageSize 2156
-#define wxSlider_GetThumbLength 2157
-#define wxSlider_GetValue 2158
-#define wxSlider_SetLineSize 2159
-#define wxSlider_SetPageSize 2160
-#define wxSlider_SetRange 2161
-#define wxSlider_SetThumbLength 2162
-#define wxSlider_SetValue 2163
-#define wxSlider_destroy 2164
-#define wxDialog_new_4 2166
-#define wxDialog_new_0 2167
-#define wxDialog_destruct 2169
-#define wxDialog_Create 2170
-#define wxDialog_CreateButtonSizer 2171
-#define wxDialog_CreateStdDialogButtonSizer 2172
-#define wxDialog_EndModal 2173
-#define wxDialog_GetAffirmativeId 2174
-#define wxDialog_GetReturnCode 2175
-#define wxDialog_IsModal 2176
-#define wxDialog_SetAffirmativeId 2177
-#define wxDialog_SetReturnCode 2178
-#define wxDialog_Show 2179
-#define wxDialog_ShowModal 2180
-#define wxColourDialog_new_0 2181
-#define wxColourDialog_new_2 2182
-#define wxColourDialog_destruct 2183
-#define wxColourDialog_Create 2184
-#define wxColourDialog_GetColourData 2185
-#define wxColourData_new_0 2186
-#define wxColourData_new_1 2187
-#define wxColourData_destruct 2188
-#define wxColourData_GetChooseFull 2189
-#define wxColourData_GetColour 2190
-#define wxColourData_GetCustomColour 2192
-#define wxColourData_SetChooseFull 2193
-#define wxColourData_SetColour 2194
-#define wxColourData_SetCustomColour 2195
-#define wxPalette_new_0 2196
-#define wxPalette_new_4 2197
-#define wxPalette_destruct 2199
-#define wxPalette_Create 2200
-#define wxPalette_GetColoursCount 2201
-#define wxPalette_GetPixel 2202
-#define wxPalette_GetRGB 2203
-#define wxPalette_IsOk 2204
-#define wxDirDialog_new 2208
-#define wxDirDialog_destruct 2209
-#define wxDirDialog_GetPath 2210
-#define wxDirDialog_GetMessage 2211
-#define wxDirDialog_SetMessage 2212
-#define wxDirDialog_SetPath 2213
-#define wxFileDialog_new 2217
-#define wxFileDialog_destruct 2218
-#define wxFileDialog_GetDirectory 2219
-#define wxFileDialog_GetFilename 2220
-#define wxFileDialog_GetFilenames 2221
-#define wxFileDialog_GetFilterIndex 2222
-#define wxFileDialog_GetMessage 2223
-#define wxFileDialog_GetPath 2224
-#define wxFileDialog_GetPaths 2225
-#define wxFileDialog_GetWildcard 2226
-#define wxFileDialog_SetDirectory 2227
-#define wxFileDialog_SetFilename 2228
-#define wxFileDialog_SetFilterIndex 2229
-#define wxFileDialog_SetMessage 2230
-#define wxFileDialog_SetPath 2231
-#define wxFileDialog_SetWildcard 2232
-#define wxPickerBase_SetInternalMargin 2233
-#define wxPickerBase_GetInternalMargin 2234
-#define wxPickerBase_SetTextCtrlProportion 2235
-#define wxPickerBase_SetPickerCtrlProportion 2236
-#define wxPickerBase_GetTextCtrlProportion 2237
-#define wxPickerBase_GetPickerCtrlProportion 2238
-#define wxPickerBase_HasTextCtrl 2239
-#define wxPickerBase_GetTextCtrl 2240
-#define wxPickerBase_IsTextCtrlGrowable 2241
-#define wxPickerBase_SetPickerCtrlGrowable 2242
-#define wxPickerBase_SetTextCtrlGrowable 2243
-#define wxPickerBase_IsPickerCtrlGrowable 2244
-#define wxFilePickerCtrl_new_0 2245
-#define wxFilePickerCtrl_new_3 2246
-#define wxFilePickerCtrl_Create 2247
-#define wxFilePickerCtrl_GetPath 2248
-#define wxFilePickerCtrl_SetPath 2249
-#define wxFilePickerCtrl_destroy 2250
-#define wxDirPickerCtrl_new_0 2251
-#define wxDirPickerCtrl_new_3 2252
-#define wxDirPickerCtrl_Create 2253
-#define wxDirPickerCtrl_GetPath 2254
-#define wxDirPickerCtrl_SetPath 2255
-#define wxDirPickerCtrl_destroy 2256
-#define wxColourPickerCtrl_new_0 2257
-#define wxColourPickerCtrl_new_3 2258
-#define wxColourPickerCtrl_Create 2259
-#define wxColourPickerCtrl_GetColour 2260
-#define wxColourPickerCtrl_SetColour_1_1 2261
-#define wxColourPickerCtrl_SetColour_1_0 2262
-#define wxColourPickerCtrl_destroy 2263
-#define wxDatePickerCtrl_new_0 2264
-#define wxDatePickerCtrl_new_3 2265
-#define wxDatePickerCtrl_GetRange 2266
-#define wxDatePickerCtrl_GetValue 2267
-#define wxDatePickerCtrl_SetRange 2268
-#define wxDatePickerCtrl_SetValue 2269
-#define wxDatePickerCtrl_destroy 2270
-#define wxFontPickerCtrl_new_0 2271
-#define wxFontPickerCtrl_new_3 2272
-#define wxFontPickerCtrl_Create 2273
-#define wxFontPickerCtrl_GetSelectedFont 2274
-#define wxFontPickerCtrl_SetSelectedFont 2275
-#define wxFontPickerCtrl_GetMaxPointSize 2276
-#define wxFontPickerCtrl_SetMaxPointSize 2277
-#define wxFontPickerCtrl_destroy 2278
-#define wxFindReplaceDialog_new_0 2281
-#define wxFindReplaceDialog_new_4 2282
-#define wxFindReplaceDialog_destruct 2283
-#define wxFindReplaceDialog_Create 2284
-#define wxFindReplaceDialog_GetData 2285
-#define wxFindReplaceData_new_0 2286
-#define wxFindReplaceData_new_1 2287
-#define wxFindReplaceData_GetFindString 2288
-#define wxFindReplaceData_GetReplaceString 2289
-#define wxFindReplaceData_GetFlags 2290
-#define wxFindReplaceData_SetFlags 2291
-#define wxFindReplaceData_SetFindString 2292
-#define wxFindReplaceData_SetReplaceString 2293
-#define wxFindReplaceData_destroy 2294
-#define wxMultiChoiceDialog_new_0 2295
-#define wxMultiChoiceDialog_new_5 2297
-#define wxMultiChoiceDialog_GetSelections 2298
-#define wxMultiChoiceDialog_SetSelections 2299
-#define wxMultiChoiceDialog_destroy 2300
-#define wxSingleChoiceDialog_new_0 2301
-#define wxSingleChoiceDialog_new_5 2303
-#define wxSingleChoiceDialog_GetSelection 2304
-#define wxSingleChoiceDialog_GetStringSelection 2305
-#define wxSingleChoiceDialog_SetSelection 2306
-#define wxSingleChoiceDialog_destroy 2307
-#define wxTextEntryDialog_new 2308
-#define wxTextEntryDialog_GetValue 2309
-#define wxTextEntryDialog_SetValue 2310
-#define wxTextEntryDialog_destroy 2311
-#define wxPasswordEntryDialog_new 2312
-#define wxPasswordEntryDialog_destroy 2313
-#define wxFontData_new_0 2314
-#define wxFontData_new_1 2315
-#define wxFontData_destruct 2316
-#define wxFontData_EnableEffects 2317
-#define wxFontData_GetAllowSymbols 2318
-#define wxFontData_GetColour 2319
-#define wxFontData_GetChosenFont 2320
-#define wxFontData_GetEnableEffects 2321
-#define wxFontData_GetInitialFont 2322
-#define wxFontData_GetShowHelp 2323
-#define wxFontData_SetAllowSymbols 2324
-#define wxFontData_SetChosenFont 2325
-#define wxFontData_SetColour 2326
-#define wxFontData_SetInitialFont 2327
-#define wxFontData_SetRange 2328
-#define wxFontData_SetShowHelp 2329
-#define wxFontDialog_new_0 2333
-#define wxFontDialog_new_2 2335
-#define wxFontDialog_Create 2337
-#define wxFontDialog_GetFontData 2338
-#define wxFontDialog_destroy 2340
-#define wxProgressDialog_new 2341
-#define wxProgressDialog_destruct 2342
-#define wxProgressDialog_Resume 2343
-#define wxProgressDialog_Update_2 2344
-#define wxProgressDialog_Update_0 2345
-#define wxMessageDialog_new 2346
-#define wxMessageDialog_destruct 2347
-#define wxPageSetupDialog_new 2348
-#define wxPageSetupDialog_destruct 2349
-#define wxPageSetupDialog_GetPageSetupData 2350
-#define wxPageSetupDialog_ShowModal 2351
-#define wxPageSetupDialogData_new_0 2352
-#define wxPageSetupDialogData_new_1_0 2353
-#define wxPageSetupDialogData_new_1_1 2354
-#define wxPageSetupDialogData_destruct 2355
-#define wxPageSetupDialogData_EnableHelp 2356
-#define wxPageSetupDialogData_EnableMargins 2357
-#define wxPageSetupDialogData_EnableOrientation 2358
-#define wxPageSetupDialogData_EnablePaper 2359
-#define wxPageSetupDialogData_EnablePrinter 2360
-#define wxPageSetupDialogData_GetDefaultMinMargins 2361
-#define wxPageSetupDialogData_GetEnableMargins 2362
-#define wxPageSetupDialogData_GetEnableOrientation 2363
-#define wxPageSetupDialogData_GetEnablePaper 2364
-#define wxPageSetupDialogData_GetEnablePrinter 2365
-#define wxPageSetupDialogData_GetEnableHelp 2366
-#define wxPageSetupDialogData_GetDefaultInfo 2367
-#define wxPageSetupDialogData_GetMarginTopLeft 2368
-#define wxPageSetupDialogData_GetMarginBottomRight 2369
-#define wxPageSetupDialogData_GetMinMarginTopLeft 2370
-#define wxPageSetupDialogData_GetMinMarginBottomRight 2371
-#define wxPageSetupDialogData_GetPaperId 2372
-#define wxPageSetupDialogData_GetPaperSize 2373
-#define wxPageSetupDialogData_GetPrintData 2375
-#define wxPageSetupDialogData_IsOk 2376
-#define wxPageSetupDialogData_SetDefaultInfo 2377
-#define wxPageSetupDialogData_SetDefaultMinMargins 2378
-#define wxPageSetupDialogData_SetMarginTopLeft 2379
-#define wxPageSetupDialogData_SetMarginBottomRight 2380
-#define wxPageSetupDialogData_SetMinMarginTopLeft 2381
-#define wxPageSetupDialogData_SetMinMarginBottomRight 2382
-#define wxPageSetupDialogData_SetPaperId 2383
-#define wxPageSetupDialogData_SetPaperSize_1_1 2384
-#define wxPageSetupDialogData_SetPaperSize_1_0 2385
-#define wxPageSetupDialogData_SetPrintData 2386
-#define wxPrintDialog_new_2_0 2387
-#define wxPrintDialog_new_2_1 2388
-#define wxPrintDialog_destruct 2389
-#define wxPrintDialog_GetPrintDialogData 2390
-#define wxPrintDialog_GetPrintDC 2391
-#define wxPrintDialogData_new_0 2392
-#define wxPrintDialogData_new_1_1 2393
-#define wxPrintDialogData_new_1_0 2394
-#define wxPrintDialogData_destruct 2395
-#define wxPrintDialogData_EnableHelp 2396
-#define wxPrintDialogData_EnablePageNumbers 2397
-#define wxPrintDialogData_EnablePrintToFile 2398
-#define wxPrintDialogData_EnableSelection 2399
-#define wxPrintDialogData_GetAllPages 2400
-#define wxPrintDialogData_GetCollate 2401
-#define wxPrintDialogData_GetFromPage 2402
-#define wxPrintDialogData_GetMaxPage 2403
-#define wxPrintDialogData_GetMinPage 2404
-#define wxPrintDialogData_GetNoCopies 2405
-#define wxPrintDialogData_GetPrintData 2406
-#define wxPrintDialogData_GetPrintToFile 2407
-#define wxPrintDialogData_GetSelection 2408
-#define wxPrintDialogData_GetToPage 2409
-#define wxPrintDialogData_IsOk 2410
-#define wxPrintDialogData_SetCollate 2411
-#define wxPrintDialogData_SetFromPage 2412
-#define wxPrintDialogData_SetMaxPage 2413
-#define wxPrintDialogData_SetMinPage 2414
-#define wxPrintDialogData_SetNoCopies 2415
-#define wxPrintDialogData_SetPrintData 2416
-#define wxPrintDialogData_SetPrintToFile 2417
-#define wxPrintDialogData_SetSelection 2418
-#define wxPrintDialogData_SetToPage 2419
-#define wxPrintData_new_0 2420
-#define wxPrintData_new_1 2421
-#define wxPrintData_destruct 2422
-#define wxPrintData_GetCollate 2423
-#define wxPrintData_GetBin 2424
-#define wxPrintData_GetColour 2425
-#define wxPrintData_GetDuplex 2426
-#define wxPrintData_GetNoCopies 2427
-#define wxPrintData_GetOrientation 2428
-#define wxPrintData_GetPaperId 2429
-#define wxPrintData_GetPrinterName 2430
-#define wxPrintData_GetQuality 2431
-#define wxPrintData_IsOk 2432
-#define wxPrintData_SetBin 2433
-#define wxPrintData_SetCollate 2434
-#define wxPrintData_SetColour 2435
-#define wxPrintData_SetDuplex 2436
-#define wxPrintData_SetNoCopies 2437
-#define wxPrintData_SetOrientation 2438
-#define wxPrintData_SetPaperId 2439
-#define wxPrintData_SetPrinterName 2440
-#define wxPrintData_SetQuality 2441
-#define wxPrintPreview_new_2 2444
-#define wxPrintPreview_new_3 2445
-#define wxPrintPreview_destruct 2447
-#define wxPrintPreview_GetCanvas 2448
-#define wxPrintPreview_GetCurrentPage 2449
-#define wxPrintPreview_GetFrame 2450
-#define wxPrintPreview_GetMaxPage 2451
-#define wxPrintPreview_GetMinPage 2452
-#define wxPrintPreview_GetPrintout 2453
-#define wxPrintPreview_GetPrintoutForPrinting 2454
-#define wxPrintPreview_IsOk 2455
-#define wxPrintPreview_PaintPage 2456
-#define wxPrintPreview_Print 2457
-#define wxPrintPreview_RenderPage 2458
-#define wxPrintPreview_SetCanvas 2459
-#define wxPrintPreview_SetCurrentPage 2460
-#define wxPrintPreview_SetFrame 2461
-#define wxPrintPreview_SetPrintout 2462
-#define wxPrintPreview_SetZoom 2463
-#define wxPreviewFrame_new 2464
-#define wxPreviewFrame_destruct 2465
-#define wxPreviewFrame_CreateControlBar 2466
-#define wxPreviewFrame_CreateCanvas 2467
-#define wxPreviewFrame_Initialize 2468
-#define wxPreviewFrame_OnCloseWindow 2469
-#define wxPreviewControlBar_new 2470
-#define wxPreviewControlBar_destruct 2471
-#define wxPreviewControlBar_CreateButtons 2472
-#define wxPreviewControlBar_GetPrintPreview 2473
-#define wxPreviewControlBar_GetZoomControl 2474
-#define wxPreviewControlBar_SetZoomControl 2475
-#define wxPrinter_new 2477
-#define wxPrinter_CreateAbortWindow 2478
-#define wxPrinter_GetAbort 2479
-#define wxPrinter_GetLastError 2480
-#define wxPrinter_GetPrintDialogData 2481
-#define wxPrinter_Print 2482
-#define wxPrinter_PrintDialog 2483
-#define wxPrinter_ReportError 2484
-#define wxPrinter_Setup 2485
-#define wxPrinter_destroy 2486
-#define wxXmlResource_new_1 2487
-#define wxXmlResource_new_2 2488
-#define wxXmlResource_destruct 2489
-#define wxXmlResource_AttachUnknownControl 2490
-#define wxXmlResource_ClearHandlers 2491
-#define wxXmlResource_CompareVersion 2492
-#define wxXmlResource_Get 2493
-#define wxXmlResource_GetFlags 2494
-#define wxXmlResource_GetVersion 2495
-#define wxXmlResource_GetXRCID 2496
-#define wxXmlResource_InitAllHandlers 2497
-#define wxXmlResource_Load 2498
-#define wxXmlResource_LoadBitmap 2499
-#define wxXmlResource_LoadDialog_2 2500
-#define wxXmlResource_LoadDialog_3 2501
-#define wxXmlResource_LoadFrame_2 2502
-#define wxXmlResource_LoadFrame_3 2503
-#define wxXmlResource_LoadIcon 2504
-#define wxXmlResource_LoadMenu 2505
-#define wxXmlResource_LoadMenuBar_2 2506
-#define wxXmlResource_LoadMenuBar_1 2507
-#define wxXmlResource_LoadPanel_2 2508
-#define wxXmlResource_LoadPanel_3 2509
-#define wxXmlResource_LoadToolBar 2510
-#define wxXmlResource_Set 2511
-#define wxXmlResource_SetFlags 2512
-#define wxXmlResource_Unload 2513
-#define wxXmlResource_xrcctrl 2514
-#define wxHtmlEasyPrinting_new 2515
-#define wxHtmlEasyPrinting_destruct 2516
-#define wxHtmlEasyPrinting_GetPrintData 2517
-#define wxHtmlEasyPrinting_GetPageSetupData 2518
-#define wxHtmlEasyPrinting_PreviewFile 2519
-#define wxHtmlEasyPrinting_PreviewText 2520
-#define wxHtmlEasyPrinting_PrintFile 2521
-#define wxHtmlEasyPrinting_PrintText 2522
-#define wxHtmlEasyPrinting_PageSetup 2523
-#define wxHtmlEasyPrinting_SetFonts 2524
-#define wxHtmlEasyPrinting_SetHeader 2525
-#define wxHtmlEasyPrinting_SetFooter 2526
-#define wxGLCanvas_new_2 2528
-#define wxGLCanvas_new_3_1 2529
-#define wxGLCanvas_new_3_0 2530
-#define wxGLCanvas_GetContext 2531
-#define wxGLCanvas_SetCurrent 2533
-#define wxGLCanvas_SwapBuffers 2534
-#define wxGLCanvas_destroy 2535
-#define wxAuiManager_new 2536
-#define wxAuiManager_destruct 2537
-#define wxAuiManager_AddPane_2_1 2538
-#define wxAuiManager_AddPane_3 2539
-#define wxAuiManager_AddPane_2_0 2540
-#define wxAuiManager_DetachPane 2541
-#define wxAuiManager_GetAllPanes 2542
-#define wxAuiManager_GetArtProvider 2543
-#define wxAuiManager_GetDockSizeConstraint 2544
-#define wxAuiManager_GetFlags 2545
-#define wxAuiManager_GetManagedWindow 2546
-#define wxAuiManager_GetManager 2547
-#define wxAuiManager_GetPane_1_1 2548
-#define wxAuiManager_GetPane_1_0 2549
-#define wxAuiManager_HideHint 2550
-#define wxAuiManager_InsertPane 2551
-#define wxAuiManager_LoadPaneInfo 2552
-#define wxAuiManager_LoadPerspective 2553
-#define wxAuiManager_SavePaneInfo 2554
-#define wxAuiManager_SavePerspective 2555
-#define wxAuiManager_SetArtProvider 2556
-#define wxAuiManager_SetDockSizeConstraint 2557
-#define wxAuiManager_SetFlags 2558
-#define wxAuiManager_SetManagedWindow 2559
-#define wxAuiManager_ShowHint 2560
-#define wxAuiManager_UnInit 2561
-#define wxAuiManager_Update 2562
-#define wxAuiPaneInfo_new_0 2563
-#define wxAuiPaneInfo_new_1 2564
-#define wxAuiPaneInfo_destruct 2565
-#define wxAuiPaneInfo_BestSize_1 2566
-#define wxAuiPaneInfo_BestSize_2 2567
-#define wxAuiPaneInfo_Bottom 2568
-#define wxAuiPaneInfo_BottomDockable 2569
-#define wxAuiPaneInfo_Caption 2570
-#define wxAuiPaneInfo_CaptionVisible 2571
-#define wxAuiPaneInfo_Centre 2572
-#define wxAuiPaneInfo_CentrePane 2573
-#define wxAuiPaneInfo_CloseButton 2574
-#define wxAuiPaneInfo_DefaultPane 2575
-#define wxAuiPaneInfo_DestroyOnClose 2576
-#define wxAuiPaneInfo_Direction 2577
-#define wxAuiPaneInfo_Dock 2578
-#define wxAuiPaneInfo_Dockable 2579
-#define wxAuiPaneInfo_Fixed 2580
-#define wxAuiPaneInfo_Float 2581
-#define wxAuiPaneInfo_Floatable 2582
-#define wxAuiPaneInfo_FloatingPosition_1 2583
-#define wxAuiPaneInfo_FloatingPosition_2 2584
-#define wxAuiPaneInfo_FloatingSize_1 2585
-#define wxAuiPaneInfo_FloatingSize_2 2586
-#define wxAuiPaneInfo_Gripper 2587
-#define wxAuiPaneInfo_GripperTop 2588
-#define wxAuiPaneInfo_HasBorder 2589
-#define wxAuiPaneInfo_HasCaption 2590
-#define wxAuiPaneInfo_HasCloseButton 2591
-#define wxAuiPaneInfo_HasFlag 2592
-#define wxAuiPaneInfo_HasGripper 2593
-#define wxAuiPaneInfo_HasGripperTop 2594
-#define wxAuiPaneInfo_HasMaximizeButton 2595
-#define wxAuiPaneInfo_HasMinimizeButton 2596
-#define wxAuiPaneInfo_HasPinButton 2597
-#define wxAuiPaneInfo_Hide 2598
-#define wxAuiPaneInfo_IsBottomDockable 2599
-#define wxAuiPaneInfo_IsDocked 2600
-#define wxAuiPaneInfo_IsFixed 2601
-#define wxAuiPaneInfo_IsFloatable 2602
-#define wxAuiPaneInfo_IsFloating 2603
-#define wxAuiPaneInfo_IsLeftDockable 2604
-#define wxAuiPaneInfo_IsMovable 2605
-#define wxAuiPaneInfo_IsOk 2606
-#define wxAuiPaneInfo_IsResizable 2607
-#define wxAuiPaneInfo_IsRightDockable 2608
-#define wxAuiPaneInfo_IsShown 2609
-#define wxAuiPaneInfo_IsToolbar 2610
-#define wxAuiPaneInfo_IsTopDockable 2611
-#define wxAuiPaneInfo_Layer 2612
-#define wxAuiPaneInfo_Left 2613
-#define wxAuiPaneInfo_LeftDockable 2614
-#define wxAuiPaneInfo_MaxSize_1 2615
-#define wxAuiPaneInfo_MaxSize_2 2616
-#define wxAuiPaneInfo_MaximizeButton 2617
-#define wxAuiPaneInfo_MinSize_1 2618
-#define wxAuiPaneInfo_MinSize_2 2619
-#define wxAuiPaneInfo_MinimizeButton 2620
-#define wxAuiPaneInfo_Movable 2621
-#define wxAuiPaneInfo_Name 2622
-#define wxAuiPaneInfo_PaneBorder 2623
-#define wxAuiPaneInfo_PinButton 2624
-#define wxAuiPaneInfo_Position 2625
-#define wxAuiPaneInfo_Resizable 2626
-#define wxAuiPaneInfo_Right 2627
-#define wxAuiPaneInfo_RightDockable 2628
-#define wxAuiPaneInfo_Row 2629
-#define wxAuiPaneInfo_SafeSet 2630
-#define wxAuiPaneInfo_SetFlag 2631
-#define wxAuiPaneInfo_Show 2632
-#define wxAuiPaneInfo_ToolbarPane 2633
-#define wxAuiPaneInfo_Top 2634
-#define wxAuiPaneInfo_TopDockable 2635
-#define wxAuiPaneInfo_Window 2636
-#define wxAuiNotebook_new_0 2637
-#define wxAuiNotebook_new_2 2638
-#define wxAuiNotebook_AddPage 2639
-#define wxAuiNotebook_Create 2640
-#define wxAuiNotebook_DeletePage 2641
-#define wxAuiNotebook_GetArtProvider 2642
-#define wxAuiNotebook_GetPage 2643
-#define wxAuiNotebook_GetPageBitmap 2644
-#define wxAuiNotebook_GetPageCount 2645
-#define wxAuiNotebook_GetPageIndex 2646
-#define wxAuiNotebook_GetPageText 2647
-#define wxAuiNotebook_GetSelection 2648
-#define wxAuiNotebook_InsertPage 2649
-#define wxAuiNotebook_RemovePage 2650
-#define wxAuiNotebook_SetArtProvider 2651
-#define wxAuiNotebook_SetFont 2652
-#define wxAuiNotebook_SetPageBitmap 2653
-#define wxAuiNotebook_SetPageText 2654
-#define wxAuiNotebook_SetSelection 2655
-#define wxAuiNotebook_SetTabCtrlHeight 2656
-#define wxAuiNotebook_SetUniformBitmapSize 2657
-#define wxAuiNotebook_destroy 2658
-#define wxMDIParentFrame_new_0 2659
-#define wxMDIParentFrame_new_4 2660
-#define wxMDIParentFrame_destruct 2661
-#define wxMDIParentFrame_ActivateNext 2662
-#define wxMDIParentFrame_ActivatePrevious 2663
-#define wxMDIParentFrame_ArrangeIcons 2664
-#define wxMDIParentFrame_Cascade 2665
-#define wxMDIParentFrame_Create 2666
-#define wxMDIParentFrame_GetActiveChild 2667
-#define wxMDIParentFrame_GetClientWindow 2668
-#define wxMDIParentFrame_Tile 2669
-#define wxMDIChildFrame_new_0 2670
-#define wxMDIChildFrame_new_4 2671
-#define wxMDIChildFrame_destruct 2672
-#define wxMDIChildFrame_Activate 2673
-#define wxMDIChildFrame_Create 2674
-#define wxMDIChildFrame_Maximize 2675
-#define wxMDIChildFrame_Restore 2676
-#define wxMDIClientWindow_new_0 2677
-#define wxMDIClientWindow_new_2 2678
-#define wxMDIClientWindow_destruct 2679
-#define wxMDIClientWindow_CreateClient 2680
-#define wxLayoutAlgorithm_new 2681
-#define wxLayoutAlgorithm_LayoutFrame 2682
-#define wxLayoutAlgorithm_LayoutMDIFrame 2683
-#define wxLayoutAlgorithm_LayoutWindow 2684
-#define wxLayoutAlgorithm_destroy 2685
-#define wxEvent_GetId 2686
-#define wxEvent_GetSkipped 2687
-#define wxEvent_GetTimestamp 2688
-#define wxEvent_IsCommandEvent 2689
-#define wxEvent_ResumePropagation 2690
-#define wxEvent_ShouldPropagate 2691
-#define wxEvent_Skip 2692
-#define wxEvent_StopPropagation 2693
-#define wxCommandEvent_getClientData 2694
-#define wxCommandEvent_GetExtraLong 2695
-#define wxCommandEvent_GetInt 2696
-#define wxCommandEvent_GetSelection 2697
-#define wxCommandEvent_GetString 2698
-#define wxCommandEvent_IsChecked 2699
-#define wxCommandEvent_IsSelection 2700
-#define wxCommandEvent_SetInt 2701
-#define wxCommandEvent_SetString 2702
-#define wxScrollEvent_GetOrientation 2703
-#define wxScrollEvent_GetPosition 2704
-#define wxScrollWinEvent_GetOrientation 2705
-#define wxScrollWinEvent_GetPosition 2706
-#define wxMouseEvent_AltDown 2707
-#define wxMouseEvent_Button 2708
-#define wxMouseEvent_ButtonDClick 2709
-#define wxMouseEvent_ButtonDown 2710
-#define wxMouseEvent_ButtonUp 2711
-#define wxMouseEvent_CmdDown 2712
-#define wxMouseEvent_ControlDown 2713
-#define wxMouseEvent_Dragging 2714
-#define wxMouseEvent_Entering 2715
-#define wxMouseEvent_GetButton 2716
-#define wxMouseEvent_GetPosition 2719
-#define wxMouseEvent_GetLogicalPosition 2720
-#define wxMouseEvent_GetLinesPerAction 2721
-#define wxMouseEvent_GetWheelRotation 2722
-#define wxMouseEvent_GetWheelDelta 2723
-#define wxMouseEvent_GetX 2724
-#define wxMouseEvent_GetY 2725
-#define wxMouseEvent_IsButton 2726
-#define wxMouseEvent_IsPageScroll 2727
-#define wxMouseEvent_Leaving 2728
-#define wxMouseEvent_LeftDClick 2729
-#define wxMouseEvent_LeftDown 2730
-#define wxMouseEvent_LeftIsDown 2731
-#define wxMouseEvent_LeftUp 2732
-#define wxMouseEvent_MetaDown 2733
-#define wxMouseEvent_MiddleDClick 2734
-#define wxMouseEvent_MiddleDown 2735
-#define wxMouseEvent_MiddleIsDown 2736
-#define wxMouseEvent_MiddleUp 2737
-#define wxMouseEvent_Moving 2738
-#define wxMouseEvent_RightDClick 2739
-#define wxMouseEvent_RightDown 2740
-#define wxMouseEvent_RightIsDown 2741
-#define wxMouseEvent_RightUp 2742
-#define wxMouseEvent_ShiftDown 2743
-#define wxSetCursorEvent_GetCursor 2744
-#define wxSetCursorEvent_GetX 2745
-#define wxSetCursorEvent_GetY 2746
-#define wxSetCursorEvent_HasCursor 2747
-#define wxSetCursorEvent_SetCursor 2748
-#define wxKeyEvent_AltDown 2749
-#define wxKeyEvent_CmdDown 2750
-#define wxKeyEvent_ControlDown 2751
-#define wxKeyEvent_GetKeyCode 2752
-#define wxKeyEvent_GetModifiers 2753
-#define wxKeyEvent_GetPosition 2756
-#define wxKeyEvent_GetRawKeyCode 2757
-#define wxKeyEvent_GetRawKeyFlags 2758
-#define wxKeyEvent_GetUnicodeKey 2759
-#define wxKeyEvent_GetX 2760
-#define wxKeyEvent_GetY 2761
-#define wxKeyEvent_HasModifiers 2762
-#define wxKeyEvent_MetaDown 2763
-#define wxKeyEvent_ShiftDown 2764
-#define wxSizeEvent_GetSize 2765
-#define wxMoveEvent_GetPosition 2766
-#define wxEraseEvent_GetDC 2767
-#define wxFocusEvent_GetWindow 2768
-#define wxChildFocusEvent_GetWindow 2769
-#define wxMenuEvent_GetMenu 2770
-#define wxMenuEvent_GetMenuId 2771
-#define wxMenuEvent_IsPopup 2772
-#define wxCloseEvent_CanVeto 2773
-#define wxCloseEvent_GetLoggingOff 2774
-#define wxCloseEvent_SetCanVeto 2775
-#define wxCloseEvent_SetLoggingOff 2776
-#define wxCloseEvent_Veto 2777
-#define wxShowEvent_SetShow 2778
-#define wxShowEvent_GetShow 2779
-#define wxIconizeEvent_Iconized 2780
-#define wxJoystickEvent_ButtonDown 2781
-#define wxJoystickEvent_ButtonIsDown 2782
-#define wxJoystickEvent_ButtonUp 2783
-#define wxJoystickEvent_GetButtonChange 2784
-#define wxJoystickEvent_GetButtonState 2785
-#define wxJoystickEvent_GetJoystick 2786
-#define wxJoystickEvent_GetPosition 2787
-#define wxJoystickEvent_GetZPosition 2788
-#define wxJoystickEvent_IsButton 2789
-#define wxJoystickEvent_IsMove 2790
-#define wxJoystickEvent_IsZMove 2791
-#define wxUpdateUIEvent_CanUpdate 2792
-#define wxUpdateUIEvent_Check 2793
-#define wxUpdateUIEvent_Enable 2794
-#define wxUpdateUIEvent_Show 2795
-#define wxUpdateUIEvent_GetChecked 2796
-#define wxUpdateUIEvent_GetEnabled 2797
-#define wxUpdateUIEvent_GetShown 2798
-#define wxUpdateUIEvent_GetSetChecked 2799
-#define wxUpdateUIEvent_GetSetEnabled 2800
-#define wxUpdateUIEvent_GetSetShown 2801
-#define wxUpdateUIEvent_GetSetText 2802
-#define wxUpdateUIEvent_GetText 2803
-#define wxUpdateUIEvent_GetMode 2804
-#define wxUpdateUIEvent_GetUpdateInterval 2805
-#define wxUpdateUIEvent_ResetUpdateTime 2806
-#define wxUpdateUIEvent_SetMode 2807
-#define wxUpdateUIEvent_SetText 2808
-#define wxUpdateUIEvent_SetUpdateInterval 2809
-#define wxMouseCaptureChangedEvent_GetCapturedWindow 2810
-#define wxPaletteChangedEvent_SetChangedWindow 2811
-#define wxPaletteChangedEvent_GetChangedWindow 2812
-#define wxQueryNewPaletteEvent_SetPaletteRealized 2813
-#define wxQueryNewPaletteEvent_GetPaletteRealized 2814
-#define wxNavigationKeyEvent_GetDirection 2815
-#define wxNavigationKeyEvent_SetDirection 2816
-#define wxNavigationKeyEvent_IsWindowChange 2817
-#define wxNavigationKeyEvent_SetWindowChange 2818
-#define wxNavigationKeyEvent_IsFromTab 2819
-#define wxNavigationKeyEvent_SetFromTab 2820
-#define wxNavigationKeyEvent_GetCurrentFocus 2821
-#define wxNavigationKeyEvent_SetCurrentFocus 2822
-#define wxHelpEvent_GetOrigin 2823
-#define wxHelpEvent_GetPosition 2824
-#define wxHelpEvent_SetOrigin 2825
-#define wxHelpEvent_SetPosition 2826
-#define wxContextMenuEvent_GetPosition 2827
-#define wxContextMenuEvent_SetPosition 2828
-#define wxIdleEvent_CanSend 2829
-#define wxIdleEvent_GetMode 2830
-#define wxIdleEvent_RequestMore 2831
-#define wxIdleEvent_MoreRequested 2832
-#define wxIdleEvent_SetMode 2833
-#define wxGridEvent_AltDown 2834
-#define wxGridEvent_ControlDown 2835
-#define wxGridEvent_GetCol 2836
-#define wxGridEvent_GetPosition 2837
-#define wxGridEvent_GetRow 2838
-#define wxGridEvent_MetaDown 2839
-#define wxGridEvent_Selecting 2840
-#define wxGridEvent_ShiftDown 2841
-#define wxNotifyEvent_Allow 2842
-#define wxNotifyEvent_IsAllowed 2843
-#define wxNotifyEvent_Veto 2844
-#define wxSashEvent_GetEdge 2845
-#define wxSashEvent_GetDragRect 2846
-#define wxSashEvent_GetDragStatus 2847
-#define wxListEvent_GetCacheFrom 2848
-#define wxListEvent_GetCacheTo 2849
-#define wxListEvent_GetKeyCode 2850
-#define wxListEvent_GetIndex 2851
-#define wxListEvent_GetColumn 2852
-#define wxListEvent_GetPoint 2853
-#define wxListEvent_GetLabel 2854
-#define wxListEvent_GetText 2855
-#define wxListEvent_GetImage 2856
-#define wxListEvent_GetData 2857
-#define wxListEvent_GetMask 2858
-#define wxListEvent_GetItem 2859
-#define wxListEvent_IsEditCancelled 2860
-#define wxDateEvent_GetDate 2861
-#define wxCalendarEvent_GetWeekDay 2862
-#define wxFileDirPickerEvent_GetPath 2863
-#define wxColourPickerEvent_GetColour 2864
-#define wxFontPickerEvent_GetFont 2865
-#define wxStyledTextEvent_GetPosition 2866
-#define wxStyledTextEvent_GetKey 2867
-#define wxStyledTextEvent_GetModifiers 2868
-#define wxStyledTextEvent_GetModificationType 2869
-#define wxStyledTextEvent_GetText 2870
-#define wxStyledTextEvent_GetLength 2871
-#define wxStyledTextEvent_GetLinesAdded 2872
-#define wxStyledTextEvent_GetLine 2873
-#define wxStyledTextEvent_GetFoldLevelNow 2874
-#define wxStyledTextEvent_GetFoldLevelPrev 2875
-#define wxStyledTextEvent_GetMargin 2876
-#define wxStyledTextEvent_GetMessage 2877
-#define wxStyledTextEvent_GetWParam 2878
-#define wxStyledTextEvent_GetLParam 2879
-#define wxStyledTextEvent_GetListType 2880
-#define wxStyledTextEvent_GetX 2881
-#define wxStyledTextEvent_GetY 2882
-#define wxStyledTextEvent_GetDragText 2883
-#define wxStyledTextEvent_GetDragAllowMove 2884
-#define wxStyledTextEvent_GetDragResult 2885
-#define wxStyledTextEvent_GetShift 2886
-#define wxStyledTextEvent_GetControl 2887
-#define wxStyledTextEvent_GetAlt 2888
-#define utils_wxGetKeyState 2889
-#define utils_wxGetMousePosition 2890
-#define utils_wxGetMouseState 2891
-#define utils_wxSetDetectableAutoRepeat 2892
-#define utils_wxBell 2893
-#define utils_wxFindMenuItemId 2894
-#define utils_wxGenericFindWindowAtPoint 2895
-#define utils_wxFindWindowAtPoint 2896
-#define utils_wxBeginBusyCursor 2897
-#define utils_wxEndBusyCursor 2898
-#define utils_wxIsBusy 2899
-#define utils_wxShutdown 2900
-#define utils_wxShell 2901
-#define utils_wxLaunchDefaultBrowser 2902
-#define utils_wxGetEmailAddress 2903
-#define utils_wxGetUserId 2904
-#define utils_wxGetHomeDir 2905
-#define utils_wxNewId 2906
-#define utils_wxRegisterId 2907
-#define utils_wxGetCurrentId 2908
-#define utils_wxGetOsDescription 2909
-#define utils_wxIsPlatformLittleEndian 2910
-#define utils_wxIsPlatform64Bit 2911
-#define wxPrintout_new 2912
-#define wxPrintout_destruct 2913
-#define wxPrintout_GetDC 2914
-#define wxPrintout_GetPageSizeMM 2915
-#define wxPrintout_GetPageSizePixels 2916
-#define wxPrintout_GetPaperRectPixels 2917
-#define wxPrintout_GetPPIPrinter 2918
-#define wxPrintout_GetPPIScreen 2919
-#define wxPrintout_GetTitle 2920
-#define wxPrintout_IsPreview 2921
-#define wxPrintout_FitThisSizeToPaper 2922
-#define wxPrintout_FitThisSizeToPage 2923
-#define wxPrintout_FitThisSizeToPageMargins 2924
-#define wxPrintout_MapScreenSizeToPaper 2925
-#define wxPrintout_MapScreenSizeToPage 2926
-#define wxPrintout_MapScreenSizeToPageMargins 2927
-#define wxPrintout_MapScreenSizeToDevice 2928
-#define wxPrintout_GetLogicalPaperRect 2929
-#define wxPrintout_GetLogicalPageRect 2930
-#define wxPrintout_GetLogicalPageMarginsRect 2931
-#define wxPrintout_SetLogicalOrigin 2932
-#define wxPrintout_OffsetLogicalOrigin 2933
-#define wxStyledTextCtrl_new_2 2934
-#define wxStyledTextCtrl_new_0 2935
-#define wxStyledTextCtrl_destruct 2936
-#define wxStyledTextCtrl_Create 2937
-#define wxStyledTextCtrl_AddText 2938
-#define wxStyledTextCtrl_AddStyledText 2939
-#define wxStyledTextCtrl_InsertText 2940
-#define wxStyledTextCtrl_ClearAll 2941
-#define wxStyledTextCtrl_ClearDocumentStyle 2942
-#define wxStyledTextCtrl_GetLength 2943
-#define wxStyledTextCtrl_GetCharAt 2944
-#define wxStyledTextCtrl_GetCurrentPos 2945
-#define wxStyledTextCtrl_GetAnchor 2946
-#define wxStyledTextCtrl_GetStyleAt 2947
-#define wxStyledTextCtrl_Redo 2948
-#define wxStyledTextCtrl_SetUndoCollection 2949
-#define wxStyledTextCtrl_SelectAll 2950
-#define wxStyledTextCtrl_SetSavePoint 2951
-#define wxStyledTextCtrl_GetStyledText 2952
-#define wxStyledTextCtrl_CanRedo 2953
-#define wxStyledTextCtrl_MarkerLineFromHandle 2954
-#define wxStyledTextCtrl_MarkerDeleteHandle 2955
-#define wxStyledTextCtrl_GetUndoCollection 2956
-#define wxStyledTextCtrl_GetViewWhiteSpace 2957
-#define wxStyledTextCtrl_SetViewWhiteSpace 2958
-#define wxStyledTextCtrl_PositionFromPoint 2959
-#define wxStyledTextCtrl_PositionFromPointClose 2960
-#define wxStyledTextCtrl_GotoLine 2961
-#define wxStyledTextCtrl_GotoPos 2962
-#define wxStyledTextCtrl_SetAnchor 2963
-#define wxStyledTextCtrl_GetCurLine 2964
-#define wxStyledTextCtrl_GetEndStyled 2965
-#define wxStyledTextCtrl_ConvertEOLs 2966
-#define wxStyledTextCtrl_GetEOLMode 2967
-#define wxStyledTextCtrl_SetEOLMode 2968
-#define wxStyledTextCtrl_StartStyling 2969
-#define wxStyledTextCtrl_SetStyling 2970
-#define wxStyledTextCtrl_GetBufferedDraw 2971
-#define wxStyledTextCtrl_SetBufferedDraw 2972
-#define wxStyledTextCtrl_SetTabWidth 2973
-#define wxStyledTextCtrl_GetTabWidth 2974
-#define wxStyledTextCtrl_SetCodePage 2975
-#define wxStyledTextCtrl_MarkerDefine 2976
-#define wxStyledTextCtrl_MarkerSetForeground 2977
-#define wxStyledTextCtrl_MarkerSetBackground 2978
-#define wxStyledTextCtrl_MarkerAdd 2979
-#define wxStyledTextCtrl_MarkerDelete 2980
-#define wxStyledTextCtrl_MarkerDeleteAll 2981
-#define wxStyledTextCtrl_MarkerGet 2982
-#define wxStyledTextCtrl_MarkerNext 2983
-#define wxStyledTextCtrl_MarkerPrevious 2984
-#define wxStyledTextCtrl_MarkerDefineBitmap 2985
-#define wxStyledTextCtrl_MarkerAddSet 2986
-#define wxStyledTextCtrl_MarkerSetAlpha 2987
-#define wxStyledTextCtrl_SetMarginType 2988
-#define wxStyledTextCtrl_GetMarginType 2989
-#define wxStyledTextCtrl_SetMarginWidth 2990
-#define wxStyledTextCtrl_GetMarginWidth 2991
-#define wxStyledTextCtrl_SetMarginMask 2992
-#define wxStyledTextCtrl_GetMarginMask 2993
-#define wxStyledTextCtrl_SetMarginSensitive 2994
-#define wxStyledTextCtrl_GetMarginSensitive 2995
-#define wxStyledTextCtrl_StyleClearAll 2996
-#define wxStyledTextCtrl_StyleSetForeground 2997
-#define wxStyledTextCtrl_StyleSetBackground 2998
-#define wxStyledTextCtrl_StyleSetBold 2999
-#define wxStyledTextCtrl_StyleSetItalic 3000
-#define wxStyledTextCtrl_StyleSetSize 3001
-#define wxStyledTextCtrl_StyleSetFaceName 3002
-#define wxStyledTextCtrl_StyleSetEOLFilled 3003
-#define wxStyledTextCtrl_StyleResetDefault 3004
-#define wxStyledTextCtrl_StyleSetUnderline 3005
-#define wxStyledTextCtrl_StyleSetCase 3006
-#define wxStyledTextCtrl_StyleSetHotSpot 3007
-#define wxStyledTextCtrl_SetSelForeground 3008
-#define wxStyledTextCtrl_SetSelBackground 3009
-#define wxStyledTextCtrl_GetSelAlpha 3010
-#define wxStyledTextCtrl_SetSelAlpha 3011
-#define wxStyledTextCtrl_SetCaretForeground 3012
-#define wxStyledTextCtrl_CmdKeyAssign 3013
-#define wxStyledTextCtrl_CmdKeyClear 3014
-#define wxStyledTextCtrl_CmdKeyClearAll 3015
-#define wxStyledTextCtrl_SetStyleBytes 3016
-#define wxStyledTextCtrl_StyleSetVisible 3017
-#define wxStyledTextCtrl_GetCaretPeriod 3018
-#define wxStyledTextCtrl_SetCaretPeriod 3019
-#define wxStyledTextCtrl_SetWordChars 3020
-#define wxStyledTextCtrl_BeginUndoAction 3021
-#define wxStyledTextCtrl_EndUndoAction 3022
-#define wxStyledTextCtrl_IndicatorSetStyle 3023
-#define wxStyledTextCtrl_IndicatorGetStyle 3024
-#define wxStyledTextCtrl_IndicatorSetForeground 3025
-#define wxStyledTextCtrl_IndicatorGetForeground 3026
-#define wxStyledTextCtrl_SetWhitespaceForeground 3027
-#define wxStyledTextCtrl_SetWhitespaceBackground 3028
-#define wxStyledTextCtrl_GetStyleBits 3029
-#define wxStyledTextCtrl_SetLineState 3030
-#define wxStyledTextCtrl_GetLineState 3031
-#define wxStyledTextCtrl_GetMaxLineState 3032
-#define wxStyledTextCtrl_GetCaretLineVisible 3033
-#define wxStyledTextCtrl_SetCaretLineVisible 3034
-#define wxStyledTextCtrl_GetCaretLineBackground 3035
-#define wxStyledTextCtrl_SetCaretLineBackground 3036
-#define wxStyledTextCtrl_AutoCompShow 3037
-#define wxStyledTextCtrl_AutoCompCancel 3038
-#define wxStyledTextCtrl_AutoCompActive 3039
-#define wxStyledTextCtrl_AutoCompPosStart 3040
-#define wxStyledTextCtrl_AutoCompComplete 3041
-#define wxStyledTextCtrl_AutoCompStops 3042
-#define wxStyledTextCtrl_AutoCompSetSeparator 3043
-#define wxStyledTextCtrl_AutoCompGetSeparator 3044
-#define wxStyledTextCtrl_AutoCompSelect 3045
-#define wxStyledTextCtrl_AutoCompSetCancelAtStart 3046
-#define wxStyledTextCtrl_AutoCompGetCancelAtStart 3047
-#define wxStyledTextCtrl_AutoCompSetFillUps 3048
-#define wxStyledTextCtrl_AutoCompSetChooseSingle 3049
-#define wxStyledTextCtrl_AutoCompGetChooseSingle 3050
-#define wxStyledTextCtrl_AutoCompSetIgnoreCase 3051
-#define wxStyledTextCtrl_AutoCompGetIgnoreCase 3052
-#define wxStyledTextCtrl_UserListShow 3053
-#define wxStyledTextCtrl_AutoCompSetAutoHide 3054
-#define wxStyledTextCtrl_AutoCompGetAutoHide 3055
-#define wxStyledTextCtrl_AutoCompSetDropRestOfWord 3056
-#define wxStyledTextCtrl_AutoCompGetDropRestOfWord 3057
-#define wxStyledTextCtrl_RegisterImage 3058
-#define wxStyledTextCtrl_ClearRegisteredImages 3059
-#define wxStyledTextCtrl_AutoCompGetTypeSeparator 3060
-#define wxStyledTextCtrl_AutoCompSetTypeSeparator 3061
-#define wxStyledTextCtrl_AutoCompSetMaxWidth 3062
-#define wxStyledTextCtrl_AutoCompGetMaxWidth 3063
-#define wxStyledTextCtrl_AutoCompSetMaxHeight 3064
-#define wxStyledTextCtrl_AutoCompGetMaxHeight 3065
-#define wxStyledTextCtrl_SetIndent 3066
-#define wxStyledTextCtrl_GetIndent 3067
-#define wxStyledTextCtrl_SetUseTabs 3068
-#define wxStyledTextCtrl_GetUseTabs 3069
-#define wxStyledTextCtrl_SetLineIndentation 3070
-#define wxStyledTextCtrl_GetLineIndentation 3071
-#define wxStyledTextCtrl_GetLineIndentPosition 3072
-#define wxStyledTextCtrl_GetColumn 3073
-#define wxStyledTextCtrl_SetUseHorizontalScrollBar 3074
-#define wxStyledTextCtrl_GetUseHorizontalScrollBar 3075
-#define wxStyledTextCtrl_SetIndentationGuides 3076
-#define wxStyledTextCtrl_GetIndentationGuides 3077
-#define wxStyledTextCtrl_SetHighlightGuide 3078
-#define wxStyledTextCtrl_GetHighlightGuide 3079
-#define wxStyledTextCtrl_GetLineEndPosition 3080
-#define wxStyledTextCtrl_GetCodePage 3081
-#define wxStyledTextCtrl_GetCaretForeground 3082
-#define wxStyledTextCtrl_GetReadOnly 3083
-#define wxStyledTextCtrl_SetCurrentPos 3084
-#define wxStyledTextCtrl_SetSelectionStart 3085
-#define wxStyledTextCtrl_GetSelectionStart 3086
-#define wxStyledTextCtrl_SetSelectionEnd 3087
-#define wxStyledTextCtrl_GetSelectionEnd 3088
-#define wxStyledTextCtrl_SetPrintMagnification 3089
-#define wxStyledTextCtrl_GetPrintMagnification 3090
-#define wxStyledTextCtrl_SetPrintColourMode 3091
-#define wxStyledTextCtrl_GetPrintColourMode 3092
-#define wxStyledTextCtrl_FindText 3093
-#define wxStyledTextCtrl_FormatRange 3094
-#define wxStyledTextCtrl_GetFirstVisibleLine 3095
-#define wxStyledTextCtrl_GetLine 3096
-#define wxStyledTextCtrl_GetLineCount 3097
-#define wxStyledTextCtrl_SetMarginLeft 3098
-#define wxStyledTextCtrl_GetMarginLeft 3099
-#define wxStyledTextCtrl_SetMarginRight 3100
-#define wxStyledTextCtrl_GetMarginRight 3101
-#define wxStyledTextCtrl_GetModify 3102
-#define wxStyledTextCtrl_SetSelection 3103
-#define wxStyledTextCtrl_GetSelectedText 3104
-#define wxStyledTextCtrl_GetTextRange 3105
-#define wxStyledTextCtrl_HideSelection 3106
-#define wxStyledTextCtrl_LineFromPosition 3107
-#define wxStyledTextCtrl_PositionFromLine 3108
-#define wxStyledTextCtrl_LineScroll 3109
-#define wxStyledTextCtrl_EnsureCaretVisible 3110
-#define wxStyledTextCtrl_ReplaceSelection 3111
-#define wxStyledTextCtrl_SetReadOnly 3112
-#define wxStyledTextCtrl_CanPaste 3113
-#define wxStyledTextCtrl_CanUndo 3114
-#define wxStyledTextCtrl_EmptyUndoBuffer 3115
-#define wxStyledTextCtrl_Undo 3116
-#define wxStyledTextCtrl_Cut 3117
-#define wxStyledTextCtrl_Copy 3118
-#define wxStyledTextCtrl_Paste 3119
-#define wxStyledTextCtrl_Clear 3120
-#define wxStyledTextCtrl_SetText 3121
-#define wxStyledTextCtrl_GetText 3122
-#define wxStyledTextCtrl_GetTextLength 3123
-#define wxStyledTextCtrl_GetOvertype 3124
-#define wxStyledTextCtrl_SetCaretWidth 3125
-#define wxStyledTextCtrl_GetCaretWidth 3126
-#define wxStyledTextCtrl_SetTargetStart 3127
-#define wxStyledTextCtrl_GetTargetStart 3128
-#define wxStyledTextCtrl_SetTargetEnd 3129
-#define wxStyledTextCtrl_GetTargetEnd 3130
-#define wxStyledTextCtrl_ReplaceTarget 3131
-#define wxStyledTextCtrl_SearchInTarget 3132
-#define wxStyledTextCtrl_SetSearchFlags 3133
-#define wxStyledTextCtrl_GetSearchFlags 3134
-#define wxStyledTextCtrl_CallTipShow 3135
-#define wxStyledTextCtrl_CallTipCancel 3136
-#define wxStyledTextCtrl_CallTipActive 3137
-#define wxStyledTextCtrl_CallTipPosAtStart 3138
-#define wxStyledTextCtrl_CallTipSetHighlight 3139
-#define wxStyledTextCtrl_CallTipSetBackground 3140
-#define wxStyledTextCtrl_CallTipSetForeground 3141
-#define wxStyledTextCtrl_CallTipSetForegroundHighlight 3142
-#define wxStyledTextCtrl_CallTipUseStyle 3143
-#define wxStyledTextCtrl_VisibleFromDocLine 3144
-#define wxStyledTextCtrl_DocLineFromVisible 3145
-#define wxStyledTextCtrl_WrapCount 3146
-#define wxStyledTextCtrl_SetFoldLevel 3147
-#define wxStyledTextCtrl_GetFoldLevel 3148
-#define wxStyledTextCtrl_GetLastChild 3149
-#define wxStyledTextCtrl_GetFoldParent 3150
-#define wxStyledTextCtrl_ShowLines 3151
-#define wxStyledTextCtrl_HideLines 3152
-#define wxStyledTextCtrl_GetLineVisible 3153
-#define wxStyledTextCtrl_SetFoldExpanded 3154
-#define wxStyledTextCtrl_GetFoldExpanded 3155
-#define wxStyledTextCtrl_ToggleFold 3156
-#define wxStyledTextCtrl_EnsureVisible 3157
-#define wxStyledTextCtrl_SetFoldFlags 3158
-#define wxStyledTextCtrl_EnsureVisibleEnforcePolicy 3159
-#define wxStyledTextCtrl_SetTabIndents 3160
-#define wxStyledTextCtrl_GetTabIndents 3161
-#define wxStyledTextCtrl_SetBackSpaceUnIndents 3162
-#define wxStyledTextCtrl_GetBackSpaceUnIndents 3163
-#define wxStyledTextCtrl_SetMouseDwellTime 3164
-#define wxStyledTextCtrl_GetMouseDwellTime 3165
-#define wxStyledTextCtrl_WordStartPosition 3166
-#define wxStyledTextCtrl_WordEndPosition 3167
-#define wxStyledTextCtrl_SetWrapMode 3168
-#define wxStyledTextCtrl_GetWrapMode 3169
-#define wxStyledTextCtrl_SetWrapVisualFlags 3170
-#define wxStyledTextCtrl_GetWrapVisualFlags 3171
-#define wxStyledTextCtrl_SetWrapVisualFlagsLocation 3172
-#define wxStyledTextCtrl_GetWrapVisualFlagsLocation 3173
-#define wxStyledTextCtrl_SetWrapStartIndent 3174
-#define wxStyledTextCtrl_GetWrapStartIndent 3175
-#define wxStyledTextCtrl_SetLayoutCache 3176
-#define wxStyledTextCtrl_GetLayoutCache 3177
-#define wxStyledTextCtrl_SetScrollWidth 3178
-#define wxStyledTextCtrl_GetScrollWidth 3179
-#define wxStyledTextCtrl_TextWidth 3180
-#define wxStyledTextCtrl_GetEndAtLastLine 3181
-#define wxStyledTextCtrl_TextHeight 3182
-#define wxStyledTextCtrl_SetUseVerticalScrollBar 3183
-#define wxStyledTextCtrl_GetUseVerticalScrollBar 3184
-#define wxStyledTextCtrl_AppendText 3185
-#define wxStyledTextCtrl_GetTwoPhaseDraw 3186
-#define wxStyledTextCtrl_SetTwoPhaseDraw 3187
-#define wxStyledTextCtrl_TargetFromSelection 3188
-#define wxStyledTextCtrl_LinesJoin 3189
-#define wxStyledTextCtrl_LinesSplit 3190
-#define wxStyledTextCtrl_SetFoldMarginColour 3191
-#define wxStyledTextCtrl_SetFoldMarginHiColour 3192
-#define wxStyledTextCtrl_LineDown 3193
-#define wxStyledTextCtrl_LineDownExtend 3194
-#define wxStyledTextCtrl_LineUp 3195
-#define wxStyledTextCtrl_LineUpExtend 3196
-#define wxStyledTextCtrl_CharLeft 3197
-#define wxStyledTextCtrl_CharLeftExtend 3198
-#define wxStyledTextCtrl_CharRight 3199
-#define wxStyledTextCtrl_CharRightExtend 3200
-#define wxStyledTextCtrl_WordLeft 3201
-#define wxStyledTextCtrl_WordLeftExtend 3202
-#define wxStyledTextCtrl_WordRight 3203
-#define wxStyledTextCtrl_WordRightExtend 3204
-#define wxStyledTextCtrl_Home 3205
-#define wxStyledTextCtrl_HomeExtend 3206
-#define wxStyledTextCtrl_LineEnd 3207
-#define wxStyledTextCtrl_LineEndExtend 3208
-#define wxStyledTextCtrl_DocumentStart 3209
-#define wxStyledTextCtrl_DocumentStartExtend 3210
-#define wxStyledTextCtrl_DocumentEnd 3211
-#define wxStyledTextCtrl_DocumentEndExtend 3212
-#define wxStyledTextCtrl_PageUp 3213
-#define wxStyledTextCtrl_PageUpExtend 3214
-#define wxStyledTextCtrl_PageDown 3215
-#define wxStyledTextCtrl_PageDownExtend 3216
-#define wxStyledTextCtrl_EditToggleOvertype 3217
-#define wxStyledTextCtrl_Cancel 3218
-#define wxStyledTextCtrl_DeleteBack 3219
-#define wxStyledTextCtrl_Tab 3220
-#define wxStyledTextCtrl_BackTab 3221
-#define wxStyledTextCtrl_NewLine 3222
-#define wxStyledTextCtrl_FormFeed 3223
-#define wxStyledTextCtrl_VCHome 3224
-#define wxStyledTextCtrl_VCHomeExtend 3225
-#define wxStyledTextCtrl_ZoomIn 3226
-#define wxStyledTextCtrl_ZoomOut 3227
-#define wxStyledTextCtrl_DelWordLeft 3228
-#define wxStyledTextCtrl_DelWordRight 3229
-#define wxStyledTextCtrl_LineCut 3230
-#define wxStyledTextCtrl_LineDelete 3231
-#define wxStyledTextCtrl_LineTranspose 3232
-#define wxStyledTextCtrl_LineDuplicate 3233
-#define wxStyledTextCtrl_LowerCase 3234
-#define wxStyledTextCtrl_UpperCase 3235
-#define wxStyledTextCtrl_LineScrollDown 3236
-#define wxStyledTextCtrl_LineScrollUp 3237
-#define wxStyledTextCtrl_DeleteBackNotLine 3238
-#define wxStyledTextCtrl_HomeDisplay 3239
-#define wxStyledTextCtrl_HomeDisplayExtend 3240
-#define wxStyledTextCtrl_LineEndDisplay 3241
-#define wxStyledTextCtrl_LineEndDisplayExtend 3242
-#define wxStyledTextCtrl_HomeWrapExtend 3243
-#define wxStyledTextCtrl_LineEndWrap 3244
-#define wxStyledTextCtrl_LineEndWrapExtend 3245
-#define wxStyledTextCtrl_VCHomeWrap 3246
-#define wxStyledTextCtrl_VCHomeWrapExtend 3247
-#define wxStyledTextCtrl_LineCopy 3248
-#define wxStyledTextCtrl_MoveCaretInsideView 3249
-#define wxStyledTextCtrl_LineLength 3250
-#define wxStyledTextCtrl_BraceHighlight 3251
-#define wxStyledTextCtrl_BraceBadLight 3252
-#define wxStyledTextCtrl_BraceMatch 3253
-#define wxStyledTextCtrl_GetViewEOL 3254
-#define wxStyledTextCtrl_SetViewEOL 3255
-#define wxStyledTextCtrl_SetModEventMask 3256
-#define wxStyledTextCtrl_GetEdgeColumn 3257
-#define wxStyledTextCtrl_SetEdgeColumn 3258
-#define wxStyledTextCtrl_GetEdgeMode 3259
-#define wxStyledTextCtrl_GetEdgeColour 3260
-#define wxStyledTextCtrl_SetEdgeColour 3261
-#define wxStyledTextCtrl_SearchAnchor 3262
-#define wxStyledTextCtrl_SearchNext 3263
-#define wxStyledTextCtrl_SearchPrev 3264
-#define wxStyledTextCtrl_LinesOnScreen 3265
-#define wxStyledTextCtrl_UsePopUp 3266
-#define wxStyledTextCtrl_SelectionIsRectangle 3267
-#define wxStyledTextCtrl_SetZoom 3268
-#define wxStyledTextCtrl_GetZoom 3269
-#define wxStyledTextCtrl_GetModEventMask 3270
-#define wxStyledTextCtrl_SetSTCFocus 3271
-#define wxStyledTextCtrl_GetSTCFocus 3272
-#define wxStyledTextCtrl_SetStatus 3273
-#define wxStyledTextCtrl_GetStatus 3274
-#define wxStyledTextCtrl_SetMouseDownCaptures 3275
-#define wxStyledTextCtrl_GetMouseDownCaptures 3276
-#define wxStyledTextCtrl_SetSTCCursor 3277
-#define wxStyledTextCtrl_GetSTCCursor 3278
-#define wxStyledTextCtrl_SetControlCharSymbol 3279
-#define wxStyledTextCtrl_GetControlCharSymbol 3280
-#define wxStyledTextCtrl_WordPartLeft 3281
-#define wxStyledTextCtrl_WordPartLeftExtend 3282
-#define wxStyledTextCtrl_WordPartRight 3283
-#define wxStyledTextCtrl_WordPartRightExtend 3284
-#define wxStyledTextCtrl_SetVisiblePolicy 3285
-#define wxStyledTextCtrl_DelLineLeft 3286
-#define wxStyledTextCtrl_DelLineRight 3287
-#define wxStyledTextCtrl_GetXOffset 3288
-#define wxStyledTextCtrl_ChooseCaretX 3289
-#define wxStyledTextCtrl_SetXCaretPolicy 3290
-#define wxStyledTextCtrl_SetYCaretPolicy 3291
-#define wxStyledTextCtrl_GetPrintWrapMode 3292
-#define wxStyledTextCtrl_SetHotspotActiveForeground 3293
-#define wxStyledTextCtrl_SetHotspotActiveBackground 3294
-#define wxStyledTextCtrl_SetHotspotActiveUnderline 3295
-#define wxStyledTextCtrl_SetHotspotSingleLine 3296
-#define wxStyledTextCtrl_ParaDownExtend 3297
-#define wxStyledTextCtrl_ParaUp 3298
-#define wxStyledTextCtrl_ParaUpExtend 3299
-#define wxStyledTextCtrl_PositionBefore 3300
-#define wxStyledTextCtrl_PositionAfter 3301
-#define wxStyledTextCtrl_CopyRange 3302
-#define wxStyledTextCtrl_CopyText 3303
-#define wxStyledTextCtrl_SetSelectionMode 3304
-#define wxStyledTextCtrl_GetSelectionMode 3305
-#define wxStyledTextCtrl_LineDownRectExtend 3306
-#define wxStyledTextCtrl_LineUpRectExtend 3307
-#define wxStyledTextCtrl_CharLeftRectExtend 3308
-#define wxStyledTextCtrl_CharRightRectExtend 3309
-#define wxStyledTextCtrl_HomeRectExtend 3310
-#define wxStyledTextCtrl_VCHomeRectExtend 3311
-#define wxStyledTextCtrl_LineEndRectExtend 3312
-#define wxStyledTextCtrl_PageUpRectExtend 3313
-#define wxStyledTextCtrl_PageDownRectExtend 3314
-#define wxStyledTextCtrl_StutteredPageUp 3315
-#define wxStyledTextCtrl_StutteredPageUpExtend 3316
-#define wxStyledTextCtrl_StutteredPageDown 3317
-#define wxStyledTextCtrl_StutteredPageDownExtend 3318
-#define wxStyledTextCtrl_WordLeftEnd 3319
-#define wxStyledTextCtrl_WordLeftEndExtend 3320
-#define wxStyledTextCtrl_WordRightEnd 3321
-#define wxStyledTextCtrl_WordRightEndExtend 3322
-#define wxStyledTextCtrl_SetWhitespaceChars 3323
-#define wxStyledTextCtrl_SetCharsDefault 3324
-#define wxStyledTextCtrl_AutoCompGetCurrent 3325
-#define wxStyledTextCtrl_Allocate 3326
-#define wxStyledTextCtrl_FindColumn 3327
-#define wxStyledTextCtrl_GetCaretSticky 3328
-#define wxStyledTextCtrl_SetCaretSticky 3329
-#define wxStyledTextCtrl_ToggleCaretSticky 3330
-#define wxStyledTextCtrl_SetPasteConvertEndings 3331
-#define wxStyledTextCtrl_GetPasteConvertEndings 3332
-#define wxStyledTextCtrl_SelectionDuplicate 3333
-#define wxStyledTextCtrl_SetCaretLineBackAlpha 3334
-#define wxStyledTextCtrl_GetCaretLineBackAlpha 3335
-#define wxStyledTextCtrl_StartRecord 3336
-#define wxStyledTextCtrl_StopRecord 3337
-#define wxStyledTextCtrl_SetLexer 3338
-#define wxStyledTextCtrl_GetLexer 3339
-#define wxStyledTextCtrl_Colourise 3340
-#define wxStyledTextCtrl_SetProperty 3341
-#define wxStyledTextCtrl_SetKeyWords 3342
-#define wxStyledTextCtrl_SetLexerLanguage 3343
-#define wxStyledTextCtrl_GetProperty 3344
-#define wxStyledTextCtrl_GetStyleBitsNeeded 3345
-#define wxStyledTextCtrl_GetCurrentLine 3346
-#define wxStyledTextCtrl_StyleSetSpec 3347
-#define wxStyledTextCtrl_StyleSetFont 3348
-#define wxStyledTextCtrl_StyleSetFontAttr 3349
-#define wxStyledTextCtrl_StyleSetCharacterSet 3350
-#define wxStyledTextCtrl_StyleSetFontEncoding 3351
-#define wxStyledTextCtrl_CmdKeyExecute 3352
-#define wxStyledTextCtrl_SetMargins 3353
-#define wxStyledTextCtrl_GetSelection 3354
-#define wxStyledTextCtrl_PointFromPosition 3355
-#define wxStyledTextCtrl_ScrollToLine 3356
-#define wxStyledTextCtrl_ScrollToColumn 3357
-#define wxStyledTextCtrl_SendMsg 3358
-#define wxStyledTextCtrl_SetVScrollBar 3359
-#define wxStyledTextCtrl_SetHScrollBar 3360
-#define wxStyledTextCtrl_GetLastKeydownProcessed 3361
-#define wxStyledTextCtrl_SetLastKeydownProcessed 3362
-#define wxStyledTextCtrl_SaveFile 3363
-#define wxStyledTextCtrl_LoadFile 3364
-#define wxStyledTextCtrl_DoDragOver 3365
-#define wxStyledTextCtrl_DoDropText 3366
-#define wxStyledTextCtrl_GetUseAntiAliasing 3367
-#define wxStyledTextCtrl_AddTextRaw 3368
-#define wxStyledTextCtrl_InsertTextRaw 3369
-#define wxStyledTextCtrl_GetCurLineRaw 3370
-#define wxStyledTextCtrl_GetLineRaw 3371
-#define wxStyledTextCtrl_GetSelectedTextRaw 3372
-#define wxStyledTextCtrl_GetTextRangeRaw 3373
-#define wxStyledTextCtrl_SetTextRaw 3374
-#define wxStyledTextCtrl_GetTextRaw 3375
-#define wxStyledTextCtrl_AppendTextRaw 3376
-#define wxArtProvider_GetBitmap 3377
-#define wxArtProvider_GetIcon 3378
-#define wxTreeEvent_GetKeyCode 3379
-#define wxTreeEvent_GetItem 3380
-#define wxTreeEvent_GetKeyEvent 3381
-#define wxTreeEvent_GetLabel 3382
-#define wxTreeEvent_GetOldItem 3383
-#define wxTreeEvent_GetPoint 3384
-#define wxTreeEvent_IsEditCancelled 3385
-#define wxTreeEvent_SetToolTip 3386
-#define wxNotebookEvent_GetOldSelection 3387
-#define wxNotebookEvent_GetSelection 3388
-#define wxNotebookEvent_SetOldSelection 3389
-#define wxNotebookEvent_SetSelection 3390
-#define wxFileDataObject_new 3391
-#define wxFileDataObject_AddFile 3392
-#define wxFileDataObject_GetFilenames 3393
-#define wxFileDataObject_destroy 3394
-#define wxTextDataObject_new 3395
-#define wxTextDataObject_GetTextLength 3396
-#define wxTextDataObject_GetText 3397
-#define wxTextDataObject_SetText 3398
-#define wxTextDataObject_destroy 3399
-#define wxBitmapDataObject_new_1_1 3400
-#define wxBitmapDataObject_new_1_0 3401
-#define wxBitmapDataObject_GetBitmap 3402
-#define wxBitmapDataObject_SetBitmap 3403
-#define wxBitmapDataObject_destroy 3404
-#define wxClipboard_new 3406
-#define wxClipboard_destruct 3407
-#define wxClipboard_AddData 3408
-#define wxClipboard_Clear 3409
-#define wxClipboard_Close 3410
-#define wxClipboard_Flush 3411
-#define wxClipboard_GetData 3412
-#define wxClipboard_IsOpened 3413
-#define wxClipboard_Open 3414
-#define wxClipboard_SetData 3415
-#define wxClipboard_UsePrimarySelection 3417
-#define wxClipboard_IsSupported 3418
-#define wxClipboard_Get 3419
-#define wxSpinEvent_GetPosition 3420
-#define wxSpinEvent_SetPosition 3421
-#define wxSplitterWindow_new_0 3422
-#define wxSplitterWindow_new_2 3423
-#define wxSplitterWindow_destruct 3424
-#define wxSplitterWindow_Create 3425
-#define wxSplitterWindow_GetMinimumPaneSize 3426
-#define wxSplitterWindow_GetSashGravity 3427
-#define wxSplitterWindow_GetSashPosition 3428
-#define wxSplitterWindow_GetSplitMode 3429
-#define wxSplitterWindow_GetWindow1 3430
-#define wxSplitterWindow_GetWindow2 3431
-#define wxSplitterWindow_Initialize 3432
-#define wxSplitterWindow_IsSplit 3433
-#define wxSplitterWindow_ReplaceWindow 3434
-#define wxSplitterWindow_SetSashGravity 3435
-#define wxSplitterWindow_SetSashPosition 3436
-#define wxSplitterWindow_SetSashSize 3437
-#define wxSplitterWindow_SetMinimumPaneSize 3438
-#define wxSplitterWindow_SetSplitMode 3439
-#define wxSplitterWindow_SplitHorizontally 3440
-#define wxSplitterWindow_SplitVertically 3441
-#define wxSplitterWindow_Unsplit 3442
-#define wxSplitterWindow_UpdateSize 3443
-#define wxSplitterEvent_GetSashPosition 3444
-#define wxSplitterEvent_GetX 3445
-#define wxSplitterEvent_GetY 3446
-#define wxSplitterEvent_GetWindowBeingRemoved 3447
-#define wxSplitterEvent_SetSashPosition 3448
-#define wxHtmlWindow_new_0 3449
-#define wxHtmlWindow_new_2 3450
-#define wxHtmlWindow_AppendToPage 3451
-#define wxHtmlWindow_GetOpenedAnchor 3452
-#define wxHtmlWindow_GetOpenedPage 3453
-#define wxHtmlWindow_GetOpenedPageTitle 3454
-#define wxHtmlWindow_GetRelatedFrame 3455
-#define wxHtmlWindow_HistoryBack 3456
-#define wxHtmlWindow_HistoryCanBack 3457
-#define wxHtmlWindow_HistoryCanForward 3458
-#define wxHtmlWindow_HistoryClear 3459
-#define wxHtmlWindow_HistoryForward 3460
-#define wxHtmlWindow_LoadFile 3461
-#define wxHtmlWindow_LoadPage 3462
-#define wxHtmlWindow_SelectAll 3463
-#define wxHtmlWindow_SelectionToText 3464
-#define wxHtmlWindow_SelectLine 3465
-#define wxHtmlWindow_SelectWord 3466
-#define wxHtmlWindow_SetBorders 3467
-#define wxHtmlWindow_SetFonts 3468
-#define wxHtmlWindow_SetPage 3469
-#define wxHtmlWindow_SetRelatedFrame 3470
-#define wxHtmlWindow_SetRelatedStatusBar 3471
-#define wxHtmlWindow_ToText 3472
-#define wxHtmlWindow_destroy 3473
-#define wxHtmlLinkEvent_GetLinkInfo 3474
-#define wxAuiNotebookEvent_SetSelection 3475
-#define wxAuiNotebookEvent_GetSelection 3476
-#define wxAuiNotebookEvent_SetOldSelection 3477
-#define wxAuiNotebookEvent_GetOldSelection 3478
-#define wxAuiNotebookEvent_SetDragSource 3479
-#define wxAuiNotebookEvent_GetDragSource 3480
-#define wxAuiManagerEvent_SetManager 3481
-#define wxAuiManagerEvent_GetManager 3482
-#define wxAuiManagerEvent_SetPane 3483
-#define wxAuiManagerEvent_GetPane 3484
-#define wxAuiManagerEvent_SetButton 3485
-#define wxAuiManagerEvent_GetButton 3486
-#define wxAuiManagerEvent_SetDC 3487
-#define wxAuiManagerEvent_GetDC 3488
-#define wxAuiManagerEvent_Veto 3489
-#define wxAuiManagerEvent_GetVeto 3490
-#define wxAuiManagerEvent_SetCanVeto 3491
-#define wxAuiManagerEvent_CanVeto 3492
-#define wxLogNull_new 3493
-#define wxLogNull_destroy 3494
+#define wxTreeCtrl_EditLabel 2010
+#define wxTreeCtrl_EnsureVisible 2011
+#define wxTreeCtrl_Expand 2012
+#define wxTreeCtrl_GetBoundingRect 2013
+#define wxTreeCtrl_GetChildrenCount 2015
+#define wxTreeCtrl_GetCount 2016
+#define wxTreeCtrl_GetEditControl 2017
+#define wxTreeCtrl_GetFirstChild 2018
+#define wxTreeCtrl_GetNextChild 2019
+#define wxTreeCtrl_GetFirstVisibleItem 2020
+#define wxTreeCtrl_GetImageList 2021
+#define wxTreeCtrl_GetIndent 2022
+#define wxTreeCtrl_GetItemBackgroundColour 2023
+#define wxTreeCtrl_GetItemData 2024
+#define wxTreeCtrl_GetItemFont 2025
+#define wxTreeCtrl_GetItemImage_1 2026
+#define wxTreeCtrl_GetItemImage_2 2027
+#define wxTreeCtrl_GetItemText 2028
+#define wxTreeCtrl_GetItemTextColour 2029
+#define wxTreeCtrl_GetLastChild 2030
+#define wxTreeCtrl_GetNextSibling 2031
+#define wxTreeCtrl_GetNextVisible 2032
+#define wxTreeCtrl_GetItemParent 2033
+#define wxTreeCtrl_GetPrevSibling 2034
+#define wxTreeCtrl_GetPrevVisible 2035
+#define wxTreeCtrl_GetRootItem 2036
+#define wxTreeCtrl_GetSelection 2037
+#define wxTreeCtrl_GetSelections 2038
+#define wxTreeCtrl_GetStateImageList 2039
+#define wxTreeCtrl_HitTest 2040
+#define wxTreeCtrl_InsertItem 2042
+#define wxTreeCtrl_IsBold 2043
+#define wxTreeCtrl_IsExpanded 2044
+#define wxTreeCtrl_IsSelected 2045
+#define wxTreeCtrl_IsVisible 2046
+#define wxTreeCtrl_ItemHasChildren 2047
+#define wxTreeCtrl_PrependItem 2048
+#define wxTreeCtrl_ScrollTo 2049
+#define wxTreeCtrl_SelectItem_1 2050
+#define wxTreeCtrl_SelectItem_2 2051
+#define wxTreeCtrl_SetIndent 2052
+#define wxTreeCtrl_SetImageList 2053
+#define wxTreeCtrl_SetItemBackgroundColour 2054
+#define wxTreeCtrl_SetItemBold 2055
+#define wxTreeCtrl_SetItemData 2056
+#define wxTreeCtrl_SetItemDropHighlight 2057
+#define wxTreeCtrl_SetItemFont 2058
+#define wxTreeCtrl_SetItemHasChildren 2059
+#define wxTreeCtrl_SetItemImage_2 2060
+#define wxTreeCtrl_SetItemImage_3 2061
+#define wxTreeCtrl_SetItemText 2062
+#define wxTreeCtrl_SetItemTextColour 2063
+#define wxTreeCtrl_SetStateImageList 2064
+#define wxTreeCtrl_SetWindowStyle 2065
+#define wxTreeCtrl_SortChildren 2066
+#define wxTreeCtrl_Toggle 2067
+#define wxTreeCtrl_ToggleItemSelection 2068
+#define wxTreeCtrl_Unselect 2069
+#define wxTreeCtrl_UnselectAll 2070
+#define wxTreeCtrl_UnselectItem 2071
+#define wxScrollBar_new_0 2072
+#define wxScrollBar_new_3 2073
+#define wxScrollBar_destruct 2074
+#define wxScrollBar_Create 2075
+#define wxScrollBar_GetRange 2076
+#define wxScrollBar_GetPageSize 2077
+#define wxScrollBar_GetThumbPosition 2078
+#define wxScrollBar_GetThumbSize 2079
+#define wxScrollBar_SetThumbPosition 2080
+#define wxScrollBar_SetScrollbar 2081
+#define wxSpinButton_new_2 2083
+#define wxSpinButton_new_0 2084
+#define wxSpinButton_Create 2085
+#define wxSpinButton_GetMax 2086
+#define wxSpinButton_GetMin 2087
+#define wxSpinButton_GetValue 2088
+#define wxSpinButton_SetRange 2089
+#define wxSpinButton_SetValue 2090
+#define wxSpinButton_destroy 2091
+#define wxSpinCtrl_new_0 2092
+#define wxSpinCtrl_new_2 2093
+#define wxSpinCtrl_Create 2095
+#define wxSpinCtrl_SetValue_1_1 2098
+#define wxSpinCtrl_SetValue_1_0 2099
+#define wxSpinCtrl_GetValue 2101
+#define wxSpinCtrl_SetRange 2103
+#define wxSpinCtrl_SetSelection 2104
+#define wxSpinCtrl_GetMin 2106
+#define wxSpinCtrl_GetMax 2108
+#define wxSpinCtrl_destroy 2109
+#define wxStaticText_new_0 2110
+#define wxStaticText_new_4 2111
+#define wxStaticText_Create 2112
+#define wxStaticText_GetLabel 2113
+#define wxStaticText_SetLabel 2114
+#define wxStaticText_Wrap 2115
+#define wxStaticText_destroy 2116
+#define wxStaticBitmap_new_0 2117
+#define wxStaticBitmap_new_4 2118
+#define wxStaticBitmap_Create 2119
+#define wxStaticBitmap_GetBitmap 2120
+#define wxStaticBitmap_SetBitmap 2121
+#define wxStaticBitmap_destroy 2122
+#define wxRadioBox_new 2123
+#define wxRadioBox_destruct 2125
+#define wxRadioBox_Create 2126
+#define wxRadioBox_Enable_2 2127
+#define wxRadioBox_Enable_1 2128
+#define wxRadioBox_GetSelection 2129
+#define wxRadioBox_GetString 2130
+#define wxRadioBox_SetSelection 2131
+#define wxRadioBox_Show_2 2132
+#define wxRadioBox_Show_1 2133
+#define wxRadioBox_GetColumnCount 2134
+#define wxRadioBox_GetItemHelpText 2135
+#define wxRadioBox_GetItemToolTip 2136
+#define wxRadioBox_GetItemFromPoint 2138
+#define wxRadioBox_GetRowCount 2139
+#define wxRadioBox_IsItemEnabled 2140
+#define wxRadioBox_IsItemShown 2141
+#define wxRadioBox_SetItemHelpText 2142
+#define wxRadioBox_SetItemToolTip 2143
+#define wxRadioButton_new_0 2144
+#define wxRadioButton_new_4 2145
+#define wxRadioButton_Create 2146
+#define wxRadioButton_GetValue 2147
+#define wxRadioButton_SetValue 2148
+#define wxRadioButton_destroy 2149
+#define wxSlider_new_6 2151
+#define wxSlider_new_0 2152
+#define wxSlider_Create 2153
+#define wxSlider_GetLineSize 2154
+#define wxSlider_GetMax 2155
+#define wxSlider_GetMin 2156
+#define wxSlider_GetPageSize 2157
+#define wxSlider_GetThumbLength 2158
+#define wxSlider_GetValue 2159
+#define wxSlider_SetLineSize 2160
+#define wxSlider_SetPageSize 2161
+#define wxSlider_SetRange 2162
+#define wxSlider_SetThumbLength 2163
+#define wxSlider_SetValue 2164
+#define wxSlider_destroy 2165
+#define wxDialog_new_4 2167
+#define wxDialog_new_0 2168
+#define wxDialog_destruct 2170
+#define wxDialog_Create 2171
+#define wxDialog_CreateButtonSizer 2172
+#define wxDialog_CreateStdDialogButtonSizer 2173
+#define wxDialog_EndModal 2174
+#define wxDialog_GetAffirmativeId 2175
+#define wxDialog_GetReturnCode 2176
+#define wxDialog_IsModal 2177
+#define wxDialog_SetAffirmativeId 2178
+#define wxDialog_SetReturnCode 2179
+#define wxDialog_Show 2180
+#define wxDialog_ShowModal 2181
+#define wxColourDialog_new_0 2182
+#define wxColourDialog_new_2 2183
+#define wxColourDialog_destruct 2184
+#define wxColourDialog_Create 2185
+#define wxColourDialog_GetColourData 2186
+#define wxColourData_new_0 2187
+#define wxColourData_new_1 2188
+#define wxColourData_destruct 2189
+#define wxColourData_GetChooseFull 2190
+#define wxColourData_GetColour 2191
+#define wxColourData_GetCustomColour 2193
+#define wxColourData_SetChooseFull 2194
+#define wxColourData_SetColour 2195
+#define wxColourData_SetCustomColour 2196
+#define wxPalette_new_0 2197
+#define wxPalette_new_4 2198
+#define wxPalette_destruct 2200
+#define wxPalette_Create 2201
+#define wxPalette_GetColoursCount 2202
+#define wxPalette_GetPixel 2203
+#define wxPalette_GetRGB 2204
+#define wxPalette_IsOk 2205
+#define wxDirDialog_new 2209
+#define wxDirDialog_destruct 2210
+#define wxDirDialog_GetPath 2211
+#define wxDirDialog_GetMessage 2212
+#define wxDirDialog_SetMessage 2213
+#define wxDirDialog_SetPath 2214
+#define wxFileDialog_new 2218
+#define wxFileDialog_destruct 2219
+#define wxFileDialog_GetDirectory 2220
+#define wxFileDialog_GetFilename 2221
+#define wxFileDialog_GetFilenames 2222
+#define wxFileDialog_GetFilterIndex 2223
+#define wxFileDialog_GetMessage 2224
+#define wxFileDialog_GetPath 2225
+#define wxFileDialog_GetPaths 2226
+#define wxFileDialog_GetWildcard 2227
+#define wxFileDialog_SetDirectory 2228
+#define wxFileDialog_SetFilename 2229
+#define wxFileDialog_SetFilterIndex 2230
+#define wxFileDialog_SetMessage 2231
+#define wxFileDialog_SetPath 2232
+#define wxFileDialog_SetWildcard 2233
+#define wxPickerBase_SetInternalMargin 2234
+#define wxPickerBase_GetInternalMargin 2235
+#define wxPickerBase_SetTextCtrlProportion 2236
+#define wxPickerBase_SetPickerCtrlProportion 2237
+#define wxPickerBase_GetTextCtrlProportion 2238
+#define wxPickerBase_GetPickerCtrlProportion 2239
+#define wxPickerBase_HasTextCtrl 2240
+#define wxPickerBase_GetTextCtrl 2241
+#define wxPickerBase_IsTextCtrlGrowable 2242
+#define wxPickerBase_SetPickerCtrlGrowable 2243
+#define wxPickerBase_SetTextCtrlGrowable 2244
+#define wxPickerBase_IsPickerCtrlGrowable 2245
+#define wxFilePickerCtrl_new_0 2246
+#define wxFilePickerCtrl_new_3 2247
+#define wxFilePickerCtrl_Create 2248
+#define wxFilePickerCtrl_GetPath 2249
+#define wxFilePickerCtrl_SetPath 2250
+#define wxFilePickerCtrl_destroy 2251
+#define wxDirPickerCtrl_new_0 2252
+#define wxDirPickerCtrl_new_3 2253
+#define wxDirPickerCtrl_Create 2254
+#define wxDirPickerCtrl_GetPath 2255
+#define wxDirPickerCtrl_SetPath 2256
+#define wxDirPickerCtrl_destroy 2257
+#define wxColourPickerCtrl_new_0 2258
+#define wxColourPickerCtrl_new_3 2259
+#define wxColourPickerCtrl_Create 2260
+#define wxColourPickerCtrl_GetColour 2261
+#define wxColourPickerCtrl_SetColour_1_1 2262
+#define wxColourPickerCtrl_SetColour_1_0 2263
+#define wxColourPickerCtrl_destroy 2264
+#define wxDatePickerCtrl_new_0 2265
+#define wxDatePickerCtrl_new_3 2266
+#define wxDatePickerCtrl_GetRange 2267
+#define wxDatePickerCtrl_GetValue 2268
+#define wxDatePickerCtrl_SetRange 2269
+#define wxDatePickerCtrl_SetValue 2270
+#define wxDatePickerCtrl_destroy 2271
+#define wxFontPickerCtrl_new_0 2272
+#define wxFontPickerCtrl_new_3 2273
+#define wxFontPickerCtrl_Create 2274
+#define wxFontPickerCtrl_GetSelectedFont 2275
+#define wxFontPickerCtrl_SetSelectedFont 2276
+#define wxFontPickerCtrl_GetMaxPointSize 2277
+#define wxFontPickerCtrl_SetMaxPointSize 2278
+#define wxFontPickerCtrl_destroy 2279
+#define wxFindReplaceDialog_new_0 2282
+#define wxFindReplaceDialog_new_4 2283
+#define wxFindReplaceDialog_destruct 2284
+#define wxFindReplaceDialog_Create 2285
+#define wxFindReplaceDialog_GetData 2286
+#define wxFindReplaceData_new_0 2287
+#define wxFindReplaceData_new_1 2288
+#define wxFindReplaceData_GetFindString 2289
+#define wxFindReplaceData_GetReplaceString 2290
+#define wxFindReplaceData_GetFlags 2291
+#define wxFindReplaceData_SetFlags 2292
+#define wxFindReplaceData_SetFindString 2293
+#define wxFindReplaceData_SetReplaceString 2294
+#define wxFindReplaceData_destroy 2295
+#define wxMultiChoiceDialog_new_0 2296
+#define wxMultiChoiceDialog_new_5 2298
+#define wxMultiChoiceDialog_GetSelections 2299
+#define wxMultiChoiceDialog_SetSelections 2300
+#define wxMultiChoiceDialog_destroy 2301
+#define wxSingleChoiceDialog_new_0 2302
+#define wxSingleChoiceDialog_new_5 2304
+#define wxSingleChoiceDialog_GetSelection 2305
+#define wxSingleChoiceDialog_GetStringSelection 2306
+#define wxSingleChoiceDialog_SetSelection 2307
+#define wxSingleChoiceDialog_destroy 2308
+#define wxTextEntryDialog_new 2309
+#define wxTextEntryDialog_GetValue 2310
+#define wxTextEntryDialog_SetValue 2311
+#define wxTextEntryDialog_destroy 2312
+#define wxPasswordEntryDialog_new 2313
+#define wxPasswordEntryDialog_destroy 2314
+#define wxFontData_new_0 2315
+#define wxFontData_new_1 2316
+#define wxFontData_destruct 2317
+#define wxFontData_EnableEffects 2318
+#define wxFontData_GetAllowSymbols 2319
+#define wxFontData_GetColour 2320
+#define wxFontData_GetChosenFont 2321
+#define wxFontData_GetEnableEffects 2322
+#define wxFontData_GetInitialFont 2323
+#define wxFontData_GetShowHelp 2324
+#define wxFontData_SetAllowSymbols 2325
+#define wxFontData_SetChosenFont 2326
+#define wxFontData_SetColour 2327
+#define wxFontData_SetInitialFont 2328
+#define wxFontData_SetRange 2329
+#define wxFontData_SetShowHelp 2330
+#define wxFontDialog_new_0 2334
+#define wxFontDialog_new_2 2336
+#define wxFontDialog_Create 2338
+#define wxFontDialog_GetFontData 2339
+#define wxFontDialog_destroy 2341
+#define wxProgressDialog_new 2342
+#define wxProgressDialog_destruct 2343
+#define wxProgressDialog_Resume 2344
+#define wxProgressDialog_Update_2 2345
+#define wxProgressDialog_Update_0 2346
+#define wxMessageDialog_new 2347
+#define wxMessageDialog_destruct 2348
+#define wxPageSetupDialog_new 2349
+#define wxPageSetupDialog_destruct 2350
+#define wxPageSetupDialog_GetPageSetupData 2351
+#define wxPageSetupDialog_ShowModal 2352
+#define wxPageSetupDialogData_new_0 2353
+#define wxPageSetupDialogData_new_1_0 2354
+#define wxPageSetupDialogData_new_1_1 2355
+#define wxPageSetupDialogData_destruct 2356
+#define wxPageSetupDialogData_EnableHelp 2357
+#define wxPageSetupDialogData_EnableMargins 2358
+#define wxPageSetupDialogData_EnableOrientation 2359
+#define wxPageSetupDialogData_EnablePaper 2360
+#define wxPageSetupDialogData_EnablePrinter 2361
+#define wxPageSetupDialogData_GetDefaultMinMargins 2362
+#define wxPageSetupDialogData_GetEnableMargins 2363
+#define wxPageSetupDialogData_GetEnableOrientation 2364
+#define wxPageSetupDialogData_GetEnablePaper 2365
+#define wxPageSetupDialogData_GetEnablePrinter 2366
+#define wxPageSetupDialogData_GetEnableHelp 2367
+#define wxPageSetupDialogData_GetDefaultInfo 2368
+#define wxPageSetupDialogData_GetMarginTopLeft 2369
+#define wxPageSetupDialogData_GetMarginBottomRight 2370
+#define wxPageSetupDialogData_GetMinMarginTopLeft 2371
+#define wxPageSetupDialogData_GetMinMarginBottomRight 2372
+#define wxPageSetupDialogData_GetPaperId 2373
+#define wxPageSetupDialogData_GetPaperSize 2374
+#define wxPageSetupDialogData_GetPrintData 2376
+#define wxPageSetupDialogData_IsOk 2377
+#define wxPageSetupDialogData_SetDefaultInfo 2378
+#define wxPageSetupDialogData_SetDefaultMinMargins 2379
+#define wxPageSetupDialogData_SetMarginTopLeft 2380
+#define wxPageSetupDialogData_SetMarginBottomRight 2381
+#define wxPageSetupDialogData_SetMinMarginTopLeft 2382
+#define wxPageSetupDialogData_SetMinMarginBottomRight 2383
+#define wxPageSetupDialogData_SetPaperId 2384
+#define wxPageSetupDialogData_SetPaperSize_1_1 2385
+#define wxPageSetupDialogData_SetPaperSize_1_0 2386
+#define wxPageSetupDialogData_SetPrintData 2387
+#define wxPrintDialog_new_2_0 2388
+#define wxPrintDialog_new_2_1 2389
+#define wxPrintDialog_destruct 2390
+#define wxPrintDialog_GetPrintDialogData 2391
+#define wxPrintDialog_GetPrintDC 2392
+#define wxPrintDialogData_new_0 2393
+#define wxPrintDialogData_new_1_1 2394
+#define wxPrintDialogData_new_1_0 2395
+#define wxPrintDialogData_destruct 2396
+#define wxPrintDialogData_EnableHelp 2397
+#define wxPrintDialogData_EnablePageNumbers 2398
+#define wxPrintDialogData_EnablePrintToFile 2399
+#define wxPrintDialogData_EnableSelection 2400
+#define wxPrintDialogData_GetAllPages 2401
+#define wxPrintDialogData_GetCollate 2402
+#define wxPrintDialogData_GetFromPage 2403
+#define wxPrintDialogData_GetMaxPage 2404
+#define wxPrintDialogData_GetMinPage 2405
+#define wxPrintDialogData_GetNoCopies 2406
+#define wxPrintDialogData_GetPrintData 2407
+#define wxPrintDialogData_GetPrintToFile 2408
+#define wxPrintDialogData_GetSelection 2409
+#define wxPrintDialogData_GetToPage 2410
+#define wxPrintDialogData_IsOk 2411
+#define wxPrintDialogData_SetCollate 2412
+#define wxPrintDialogData_SetFromPage 2413
+#define wxPrintDialogData_SetMaxPage 2414
+#define wxPrintDialogData_SetMinPage 2415
+#define wxPrintDialogData_SetNoCopies 2416
+#define wxPrintDialogData_SetPrintData 2417
+#define wxPrintDialogData_SetPrintToFile 2418
+#define wxPrintDialogData_SetSelection 2419
+#define wxPrintDialogData_SetToPage 2420
+#define wxPrintData_new_0 2421
+#define wxPrintData_new_1 2422
+#define wxPrintData_destruct 2423
+#define wxPrintData_GetCollate 2424
+#define wxPrintData_GetBin 2425
+#define wxPrintData_GetColour 2426
+#define wxPrintData_GetDuplex 2427
+#define wxPrintData_GetNoCopies 2428
+#define wxPrintData_GetOrientation 2429
+#define wxPrintData_GetPaperId 2430
+#define wxPrintData_GetPrinterName 2431
+#define wxPrintData_GetQuality 2432
+#define wxPrintData_IsOk 2433
+#define wxPrintData_SetBin 2434
+#define wxPrintData_SetCollate 2435
+#define wxPrintData_SetColour 2436
+#define wxPrintData_SetDuplex 2437
+#define wxPrintData_SetNoCopies 2438
+#define wxPrintData_SetOrientation 2439
+#define wxPrintData_SetPaperId 2440
+#define wxPrintData_SetPrinterName 2441
+#define wxPrintData_SetQuality 2442
+#define wxPrintPreview_new_2 2445
+#define wxPrintPreview_new_3 2446
+#define wxPrintPreview_destruct 2448
+#define wxPrintPreview_GetCanvas 2449
+#define wxPrintPreview_GetCurrentPage 2450
+#define wxPrintPreview_GetFrame 2451
+#define wxPrintPreview_GetMaxPage 2452
+#define wxPrintPreview_GetMinPage 2453
+#define wxPrintPreview_GetPrintout 2454
+#define wxPrintPreview_GetPrintoutForPrinting 2455
+#define wxPrintPreview_IsOk 2456
+#define wxPrintPreview_PaintPage 2457
+#define wxPrintPreview_Print 2458
+#define wxPrintPreview_RenderPage 2459
+#define wxPrintPreview_SetCanvas 2460
+#define wxPrintPreview_SetCurrentPage 2461
+#define wxPrintPreview_SetFrame 2462
+#define wxPrintPreview_SetPrintout 2463
+#define wxPrintPreview_SetZoom 2464
+#define wxPreviewFrame_new 2465
+#define wxPreviewFrame_destruct 2466
+#define wxPreviewFrame_CreateControlBar 2467
+#define wxPreviewFrame_CreateCanvas 2468
+#define wxPreviewFrame_Initialize 2469
+#define wxPreviewFrame_OnCloseWindow 2470
+#define wxPreviewControlBar_new 2471
+#define wxPreviewControlBar_destruct 2472
+#define wxPreviewControlBar_CreateButtons 2473
+#define wxPreviewControlBar_GetPrintPreview 2474
+#define wxPreviewControlBar_GetZoomControl 2475
+#define wxPreviewControlBar_SetZoomControl 2476
+#define wxPrinter_new 2478
+#define wxPrinter_CreateAbortWindow 2479
+#define wxPrinter_GetAbort 2480
+#define wxPrinter_GetLastError 2481
+#define wxPrinter_GetPrintDialogData 2482
+#define wxPrinter_Print 2483
+#define wxPrinter_PrintDialog 2484
+#define wxPrinter_ReportError 2485
+#define wxPrinter_Setup 2486
+#define wxPrinter_destroy 2487
+#define wxXmlResource_new_1 2488
+#define wxXmlResource_new_2 2489
+#define wxXmlResource_destruct 2490
+#define wxXmlResource_AttachUnknownControl 2491
+#define wxXmlResource_ClearHandlers 2492
+#define wxXmlResource_CompareVersion 2493
+#define wxXmlResource_Get 2494
+#define wxXmlResource_GetFlags 2495
+#define wxXmlResource_GetVersion 2496
+#define wxXmlResource_GetXRCID 2497
+#define wxXmlResource_InitAllHandlers 2498
+#define wxXmlResource_Load 2499
+#define wxXmlResource_LoadBitmap 2500
+#define wxXmlResource_LoadDialog_2 2501
+#define wxXmlResource_LoadDialog_3 2502
+#define wxXmlResource_LoadFrame_2 2503
+#define wxXmlResource_LoadFrame_3 2504
+#define wxXmlResource_LoadIcon 2505
+#define wxXmlResource_LoadMenu 2506
+#define wxXmlResource_LoadMenuBar_2 2507
+#define wxXmlResource_LoadMenuBar_1 2508
+#define wxXmlResource_LoadPanel_2 2509
+#define wxXmlResource_LoadPanel_3 2510
+#define wxXmlResource_LoadToolBar 2511
+#define wxXmlResource_Set 2512
+#define wxXmlResource_SetFlags 2513
+#define wxXmlResource_Unload 2514
+#define wxXmlResource_xrcctrl 2515
+#define wxHtmlEasyPrinting_new 2516
+#define wxHtmlEasyPrinting_destruct 2517
+#define wxHtmlEasyPrinting_GetPrintData 2518
+#define wxHtmlEasyPrinting_GetPageSetupData 2519
+#define wxHtmlEasyPrinting_PreviewFile 2520
+#define wxHtmlEasyPrinting_PreviewText 2521
+#define wxHtmlEasyPrinting_PrintFile 2522
+#define wxHtmlEasyPrinting_PrintText 2523
+#define wxHtmlEasyPrinting_PageSetup 2524
+#define wxHtmlEasyPrinting_SetFonts 2525
+#define wxHtmlEasyPrinting_SetHeader 2526
+#define wxHtmlEasyPrinting_SetFooter 2527
+#define wxGLCanvas_new_2 2529
+#define wxGLCanvas_new_3_1 2530
+#define wxGLCanvas_new_3_0 2531
+#define wxGLCanvas_GetContext 2532
+#define wxGLCanvas_SetCurrent 2534
+#define wxGLCanvas_SwapBuffers 2535
+#define wxGLCanvas_destroy 2536
+#define wxAuiManager_new 2537
+#define wxAuiManager_destruct 2538
+#define wxAuiManager_AddPane_2_1 2539
+#define wxAuiManager_AddPane_3 2540
+#define wxAuiManager_AddPane_2_0 2541
+#define wxAuiManager_DetachPane 2542
+#define wxAuiManager_GetAllPanes 2543
+#define wxAuiManager_GetArtProvider 2544
+#define wxAuiManager_GetDockSizeConstraint 2545
+#define wxAuiManager_GetFlags 2546
+#define wxAuiManager_GetManagedWindow 2547
+#define wxAuiManager_GetManager 2548
+#define wxAuiManager_GetPane_1_1 2549
+#define wxAuiManager_GetPane_1_0 2550
+#define wxAuiManager_HideHint 2551
+#define wxAuiManager_InsertPane 2552
+#define wxAuiManager_LoadPaneInfo 2553
+#define wxAuiManager_LoadPerspective 2554
+#define wxAuiManager_SavePaneInfo 2555
+#define wxAuiManager_SavePerspective 2556
+#define wxAuiManager_SetArtProvider 2557
+#define wxAuiManager_SetDockSizeConstraint 2558
+#define wxAuiManager_SetFlags 2559
+#define wxAuiManager_SetManagedWindow 2560
+#define wxAuiManager_ShowHint 2561
+#define wxAuiManager_UnInit 2562
+#define wxAuiManager_Update 2563
+#define wxAuiPaneInfo_new_0 2564
+#define wxAuiPaneInfo_new_1 2565
+#define wxAuiPaneInfo_destruct 2566
+#define wxAuiPaneInfo_BestSize_1 2567
+#define wxAuiPaneInfo_BestSize_2 2568
+#define wxAuiPaneInfo_Bottom 2569
+#define wxAuiPaneInfo_BottomDockable 2570
+#define wxAuiPaneInfo_Caption 2571
+#define wxAuiPaneInfo_CaptionVisible 2572
+#define wxAuiPaneInfo_Centre 2573
+#define wxAuiPaneInfo_CentrePane 2574
+#define wxAuiPaneInfo_CloseButton 2575
+#define wxAuiPaneInfo_DefaultPane 2576
+#define wxAuiPaneInfo_DestroyOnClose 2577
+#define wxAuiPaneInfo_Direction 2578
+#define wxAuiPaneInfo_Dock 2579
+#define wxAuiPaneInfo_Dockable 2580
+#define wxAuiPaneInfo_Fixed 2581
+#define wxAuiPaneInfo_Float 2582
+#define wxAuiPaneInfo_Floatable 2583
+#define wxAuiPaneInfo_FloatingPosition_1 2584
+#define wxAuiPaneInfo_FloatingPosition_2 2585
+#define wxAuiPaneInfo_FloatingSize_1 2586
+#define wxAuiPaneInfo_FloatingSize_2 2587
+#define wxAuiPaneInfo_Gripper 2588
+#define wxAuiPaneInfo_GripperTop 2589
+#define wxAuiPaneInfo_HasBorder 2590
+#define wxAuiPaneInfo_HasCaption 2591
+#define wxAuiPaneInfo_HasCloseButton 2592
+#define wxAuiPaneInfo_HasFlag 2593
+#define wxAuiPaneInfo_HasGripper 2594
+#define wxAuiPaneInfo_HasGripperTop 2595
+#define wxAuiPaneInfo_HasMaximizeButton 2596
+#define wxAuiPaneInfo_HasMinimizeButton 2597
+#define wxAuiPaneInfo_HasPinButton 2598
+#define wxAuiPaneInfo_Hide 2599
+#define wxAuiPaneInfo_IsBottomDockable 2600
+#define wxAuiPaneInfo_IsDocked 2601
+#define wxAuiPaneInfo_IsFixed 2602
+#define wxAuiPaneInfo_IsFloatable 2603
+#define wxAuiPaneInfo_IsFloating 2604
+#define wxAuiPaneInfo_IsLeftDockable 2605
+#define wxAuiPaneInfo_IsMovable 2606
+#define wxAuiPaneInfo_IsOk 2607
+#define wxAuiPaneInfo_IsResizable 2608
+#define wxAuiPaneInfo_IsRightDockable 2609
+#define wxAuiPaneInfo_IsShown 2610
+#define wxAuiPaneInfo_IsToolbar 2611
+#define wxAuiPaneInfo_IsTopDockable 2612
+#define wxAuiPaneInfo_Layer 2613
+#define wxAuiPaneInfo_Left 2614
+#define wxAuiPaneInfo_LeftDockable 2615
+#define wxAuiPaneInfo_MaxSize_1 2616
+#define wxAuiPaneInfo_MaxSize_2 2617
+#define wxAuiPaneInfo_MaximizeButton 2618
+#define wxAuiPaneInfo_MinSize_1 2619
+#define wxAuiPaneInfo_MinSize_2 2620
+#define wxAuiPaneInfo_MinimizeButton 2621
+#define wxAuiPaneInfo_Movable 2622
+#define wxAuiPaneInfo_Name 2623
+#define wxAuiPaneInfo_PaneBorder 2624
+#define wxAuiPaneInfo_PinButton 2625
+#define wxAuiPaneInfo_Position 2626
+#define wxAuiPaneInfo_Resizable 2627
+#define wxAuiPaneInfo_Right 2628
+#define wxAuiPaneInfo_RightDockable 2629
+#define wxAuiPaneInfo_Row 2630
+#define wxAuiPaneInfo_SafeSet 2631
+#define wxAuiPaneInfo_SetFlag 2632
+#define wxAuiPaneInfo_Show 2633
+#define wxAuiPaneInfo_ToolbarPane 2634
+#define wxAuiPaneInfo_Top 2635
+#define wxAuiPaneInfo_TopDockable 2636
+#define wxAuiPaneInfo_Window 2637
+#define wxAuiNotebook_new_0 2638
+#define wxAuiNotebook_new_2 2639
+#define wxAuiNotebook_AddPage 2640
+#define wxAuiNotebook_Create 2641
+#define wxAuiNotebook_DeletePage 2642
+#define wxAuiNotebook_GetArtProvider 2643
+#define wxAuiNotebook_GetPage 2644
+#define wxAuiNotebook_GetPageBitmap 2645
+#define wxAuiNotebook_GetPageCount 2646
+#define wxAuiNotebook_GetPageIndex 2647
+#define wxAuiNotebook_GetPageText 2648
+#define wxAuiNotebook_GetSelection 2649
+#define wxAuiNotebook_InsertPage 2650
+#define wxAuiNotebook_RemovePage 2651
+#define wxAuiNotebook_SetArtProvider 2652
+#define wxAuiNotebook_SetFont 2653
+#define wxAuiNotebook_SetPageBitmap 2654
+#define wxAuiNotebook_SetPageText 2655
+#define wxAuiNotebook_SetSelection 2656
+#define wxAuiNotebook_SetTabCtrlHeight 2657
+#define wxAuiNotebook_SetUniformBitmapSize 2658
+#define wxAuiNotebook_destroy 2659
+#define wxMDIParentFrame_new_0 2660
+#define wxMDIParentFrame_new_4 2661
+#define wxMDIParentFrame_destruct 2662
+#define wxMDIParentFrame_ActivateNext 2663
+#define wxMDIParentFrame_ActivatePrevious 2664
+#define wxMDIParentFrame_ArrangeIcons 2665
+#define wxMDIParentFrame_Cascade 2666
+#define wxMDIParentFrame_Create 2667
+#define wxMDIParentFrame_GetActiveChild 2668
+#define wxMDIParentFrame_GetClientWindow 2669
+#define wxMDIParentFrame_Tile 2670
+#define wxMDIChildFrame_new_0 2671
+#define wxMDIChildFrame_new_4 2672
+#define wxMDIChildFrame_destruct 2673
+#define wxMDIChildFrame_Activate 2674
+#define wxMDIChildFrame_Create 2675
+#define wxMDIChildFrame_Maximize 2676
+#define wxMDIChildFrame_Restore 2677
+#define wxMDIClientWindow_new_0 2678
+#define wxMDIClientWindow_new_2 2679
+#define wxMDIClientWindow_destruct 2680
+#define wxMDIClientWindow_CreateClient 2681
+#define wxLayoutAlgorithm_new 2682
+#define wxLayoutAlgorithm_LayoutFrame 2683
+#define wxLayoutAlgorithm_LayoutMDIFrame 2684
+#define wxLayoutAlgorithm_LayoutWindow 2685
+#define wxLayoutAlgorithm_destroy 2686
+#define wxEvent_GetId 2687
+#define wxEvent_GetSkipped 2688
+#define wxEvent_GetTimestamp 2689
+#define wxEvent_IsCommandEvent 2690
+#define wxEvent_ResumePropagation 2691
+#define wxEvent_ShouldPropagate 2692
+#define wxEvent_Skip 2693
+#define wxEvent_StopPropagation 2694
+#define wxCommandEvent_getClientData 2695
+#define wxCommandEvent_GetExtraLong 2696
+#define wxCommandEvent_GetInt 2697
+#define wxCommandEvent_GetSelection 2698
+#define wxCommandEvent_GetString 2699
+#define wxCommandEvent_IsChecked 2700
+#define wxCommandEvent_IsSelection 2701
+#define wxCommandEvent_SetInt 2702
+#define wxCommandEvent_SetString 2703
+#define wxScrollEvent_GetOrientation 2704
+#define wxScrollEvent_GetPosition 2705
+#define wxScrollWinEvent_GetOrientation 2706
+#define wxScrollWinEvent_GetPosition 2707
+#define wxMouseEvent_AltDown 2708
+#define wxMouseEvent_Button 2709
+#define wxMouseEvent_ButtonDClick 2710
+#define wxMouseEvent_ButtonDown 2711
+#define wxMouseEvent_ButtonUp 2712
+#define wxMouseEvent_CmdDown 2713
+#define wxMouseEvent_ControlDown 2714
+#define wxMouseEvent_Dragging 2715
+#define wxMouseEvent_Entering 2716
+#define wxMouseEvent_GetButton 2717
+#define wxMouseEvent_GetPosition 2720
+#define wxMouseEvent_GetLogicalPosition 2721
+#define wxMouseEvent_GetLinesPerAction 2722
+#define wxMouseEvent_GetWheelRotation 2723
+#define wxMouseEvent_GetWheelDelta 2724
+#define wxMouseEvent_GetX 2725
+#define wxMouseEvent_GetY 2726
+#define wxMouseEvent_IsButton 2727
+#define wxMouseEvent_IsPageScroll 2728
+#define wxMouseEvent_Leaving 2729
+#define wxMouseEvent_LeftDClick 2730
+#define wxMouseEvent_LeftDown 2731
+#define wxMouseEvent_LeftIsDown 2732
+#define wxMouseEvent_LeftUp 2733
+#define wxMouseEvent_MetaDown 2734
+#define wxMouseEvent_MiddleDClick 2735
+#define wxMouseEvent_MiddleDown 2736
+#define wxMouseEvent_MiddleIsDown 2737
+#define wxMouseEvent_MiddleUp 2738
+#define wxMouseEvent_Moving 2739
+#define wxMouseEvent_RightDClick 2740
+#define wxMouseEvent_RightDown 2741
+#define wxMouseEvent_RightIsDown 2742
+#define wxMouseEvent_RightUp 2743
+#define wxMouseEvent_ShiftDown 2744
+#define wxSetCursorEvent_GetCursor 2745
+#define wxSetCursorEvent_GetX 2746
+#define wxSetCursorEvent_GetY 2747
+#define wxSetCursorEvent_HasCursor 2748
+#define wxSetCursorEvent_SetCursor 2749
+#define wxKeyEvent_AltDown 2750
+#define wxKeyEvent_CmdDown 2751
+#define wxKeyEvent_ControlDown 2752
+#define wxKeyEvent_GetKeyCode 2753
+#define wxKeyEvent_GetModifiers 2754
+#define wxKeyEvent_GetPosition 2757
+#define wxKeyEvent_GetRawKeyCode 2758
+#define wxKeyEvent_GetRawKeyFlags 2759
+#define wxKeyEvent_GetUnicodeKey 2760
+#define wxKeyEvent_GetX 2761
+#define wxKeyEvent_GetY 2762
+#define wxKeyEvent_HasModifiers 2763
+#define wxKeyEvent_MetaDown 2764
+#define wxKeyEvent_ShiftDown 2765
+#define wxSizeEvent_GetSize 2766
+#define wxMoveEvent_GetPosition 2767
+#define wxEraseEvent_GetDC 2768
+#define wxFocusEvent_GetWindow 2769
+#define wxChildFocusEvent_GetWindow 2770
+#define wxMenuEvent_GetMenu 2771
+#define wxMenuEvent_GetMenuId 2772
+#define wxMenuEvent_IsPopup 2773
+#define wxCloseEvent_CanVeto 2774
+#define wxCloseEvent_GetLoggingOff 2775
+#define wxCloseEvent_SetCanVeto 2776
+#define wxCloseEvent_SetLoggingOff 2777
+#define wxCloseEvent_Veto 2778
+#define wxShowEvent_SetShow 2779
+#define wxShowEvent_GetShow 2780
+#define wxIconizeEvent_Iconized 2781
+#define wxJoystickEvent_ButtonDown 2782
+#define wxJoystickEvent_ButtonIsDown 2783
+#define wxJoystickEvent_ButtonUp 2784
+#define wxJoystickEvent_GetButtonChange 2785
+#define wxJoystickEvent_GetButtonState 2786
+#define wxJoystickEvent_GetJoystick 2787
+#define wxJoystickEvent_GetPosition 2788
+#define wxJoystickEvent_GetZPosition 2789
+#define wxJoystickEvent_IsButton 2790
+#define wxJoystickEvent_IsMove 2791
+#define wxJoystickEvent_IsZMove 2792
+#define wxUpdateUIEvent_CanUpdate 2793
+#define wxUpdateUIEvent_Check 2794
+#define wxUpdateUIEvent_Enable 2795
+#define wxUpdateUIEvent_Show 2796
+#define wxUpdateUIEvent_GetChecked 2797
+#define wxUpdateUIEvent_GetEnabled 2798
+#define wxUpdateUIEvent_GetShown 2799
+#define wxUpdateUIEvent_GetSetChecked 2800
+#define wxUpdateUIEvent_GetSetEnabled 2801
+#define wxUpdateUIEvent_GetSetShown 2802
+#define wxUpdateUIEvent_GetSetText 2803
+#define wxUpdateUIEvent_GetText 2804
+#define wxUpdateUIEvent_GetMode 2805
+#define wxUpdateUIEvent_GetUpdateInterval 2806
+#define wxUpdateUIEvent_ResetUpdateTime 2807
+#define wxUpdateUIEvent_SetMode 2808
+#define wxUpdateUIEvent_SetText 2809
+#define wxUpdateUIEvent_SetUpdateInterval 2810
+#define wxMouseCaptureChangedEvent_GetCapturedWindow 2811
+#define wxPaletteChangedEvent_SetChangedWindow 2812
+#define wxPaletteChangedEvent_GetChangedWindow 2813
+#define wxQueryNewPaletteEvent_SetPaletteRealized 2814
+#define wxQueryNewPaletteEvent_GetPaletteRealized 2815
+#define wxNavigationKeyEvent_GetDirection 2816
+#define wxNavigationKeyEvent_SetDirection 2817
+#define wxNavigationKeyEvent_IsWindowChange 2818
+#define wxNavigationKeyEvent_SetWindowChange 2819
+#define wxNavigationKeyEvent_IsFromTab 2820
+#define wxNavigationKeyEvent_SetFromTab 2821
+#define wxNavigationKeyEvent_GetCurrentFocus 2822
+#define wxNavigationKeyEvent_SetCurrentFocus 2823
+#define wxHelpEvent_GetOrigin 2824
+#define wxHelpEvent_GetPosition 2825
+#define wxHelpEvent_SetOrigin 2826
+#define wxHelpEvent_SetPosition 2827
+#define wxContextMenuEvent_GetPosition 2828
+#define wxContextMenuEvent_SetPosition 2829
+#define wxIdleEvent_CanSend 2830
+#define wxIdleEvent_GetMode 2831
+#define wxIdleEvent_RequestMore 2832
+#define wxIdleEvent_MoreRequested 2833
+#define wxIdleEvent_SetMode 2834
+#define wxGridEvent_AltDown 2835
+#define wxGridEvent_ControlDown 2836
+#define wxGridEvent_GetCol 2837
+#define wxGridEvent_GetPosition 2838
+#define wxGridEvent_GetRow 2839
+#define wxGridEvent_MetaDown 2840
+#define wxGridEvent_Selecting 2841
+#define wxGridEvent_ShiftDown 2842
+#define wxNotifyEvent_Allow 2843
+#define wxNotifyEvent_IsAllowed 2844
+#define wxNotifyEvent_Veto 2845
+#define wxSashEvent_GetEdge 2846
+#define wxSashEvent_GetDragRect 2847
+#define wxSashEvent_GetDragStatus 2848
+#define wxListEvent_GetCacheFrom 2849
+#define wxListEvent_GetCacheTo 2850
+#define wxListEvent_GetKeyCode 2851
+#define wxListEvent_GetIndex 2852
+#define wxListEvent_GetColumn 2853
+#define wxListEvent_GetPoint 2854
+#define wxListEvent_GetLabel 2855
+#define wxListEvent_GetText 2856
+#define wxListEvent_GetImage 2857
+#define wxListEvent_GetData 2858
+#define wxListEvent_GetMask 2859
+#define wxListEvent_GetItem 2860
+#define wxListEvent_IsEditCancelled 2861
+#define wxDateEvent_GetDate 2862
+#define wxCalendarEvent_GetWeekDay 2863
+#define wxFileDirPickerEvent_GetPath 2864
+#define wxColourPickerEvent_GetColour 2865
+#define wxFontPickerEvent_GetFont 2866
+#define wxStyledTextEvent_GetPosition 2867
+#define wxStyledTextEvent_GetKey 2868
+#define wxStyledTextEvent_GetModifiers 2869
+#define wxStyledTextEvent_GetModificationType 2870
+#define wxStyledTextEvent_GetText 2871
+#define wxStyledTextEvent_GetLength 2872
+#define wxStyledTextEvent_GetLinesAdded 2873
+#define wxStyledTextEvent_GetLine 2874
+#define wxStyledTextEvent_GetFoldLevelNow 2875
+#define wxStyledTextEvent_GetFoldLevelPrev 2876
+#define wxStyledTextEvent_GetMargin 2877
+#define wxStyledTextEvent_GetMessage 2878
+#define wxStyledTextEvent_GetWParam 2879
+#define wxStyledTextEvent_GetLParam 2880
+#define wxStyledTextEvent_GetListType 2881
+#define wxStyledTextEvent_GetX 2882
+#define wxStyledTextEvent_GetY 2883
+#define wxStyledTextEvent_GetDragText 2884
+#define wxStyledTextEvent_GetDragAllowMove 2885
+#define wxStyledTextEvent_GetDragResult 2886
+#define wxStyledTextEvent_GetShift 2887
+#define wxStyledTextEvent_GetControl 2888
+#define wxStyledTextEvent_GetAlt 2889
+#define utils_wxGetKeyState 2890
+#define utils_wxGetMousePosition 2891
+#define utils_wxGetMouseState 2892
+#define utils_wxSetDetectableAutoRepeat 2893
+#define utils_wxBell 2894
+#define utils_wxFindMenuItemId 2895
+#define utils_wxGenericFindWindowAtPoint 2896
+#define utils_wxFindWindowAtPoint 2897
+#define utils_wxBeginBusyCursor 2898
+#define utils_wxEndBusyCursor 2899
+#define utils_wxIsBusy 2900
+#define utils_wxShutdown 2901
+#define utils_wxShell 2902
+#define utils_wxLaunchDefaultBrowser 2903
+#define utils_wxGetEmailAddress 2904
+#define utils_wxGetUserId 2905
+#define utils_wxGetHomeDir 2906
+#define utils_wxNewId 2907
+#define utils_wxRegisterId 2908
+#define utils_wxGetCurrentId 2909
+#define utils_wxGetOsDescription 2910
+#define utils_wxIsPlatformLittleEndian 2911
+#define utils_wxIsPlatform64Bit 2912
+#define wxPrintout_new 2913
+#define wxPrintout_destruct 2914
+#define wxPrintout_GetDC 2915
+#define wxPrintout_GetPageSizeMM 2916
+#define wxPrintout_GetPageSizePixels 2917
+#define wxPrintout_GetPaperRectPixels 2918
+#define wxPrintout_GetPPIPrinter 2919
+#define wxPrintout_GetPPIScreen 2920
+#define wxPrintout_GetTitle 2921
+#define wxPrintout_IsPreview 2922
+#define wxPrintout_FitThisSizeToPaper 2923
+#define wxPrintout_FitThisSizeToPage 2924
+#define wxPrintout_FitThisSizeToPageMargins 2925
+#define wxPrintout_MapScreenSizeToPaper 2926
+#define wxPrintout_MapScreenSizeToPage 2927
+#define wxPrintout_MapScreenSizeToPageMargins 2928
+#define wxPrintout_MapScreenSizeToDevice 2929
+#define wxPrintout_GetLogicalPaperRect 2930
+#define wxPrintout_GetLogicalPageRect 2931
+#define wxPrintout_GetLogicalPageMarginsRect 2932
+#define wxPrintout_SetLogicalOrigin 2933
+#define wxPrintout_OffsetLogicalOrigin 2934
+#define wxStyledTextCtrl_new_2 2935
+#define wxStyledTextCtrl_new_0 2936
+#define wxStyledTextCtrl_destruct 2937
+#define wxStyledTextCtrl_Create 2938
+#define wxStyledTextCtrl_AddText 2939
+#define wxStyledTextCtrl_AddStyledText 2940
+#define wxStyledTextCtrl_InsertText 2941
+#define wxStyledTextCtrl_ClearAll 2942
+#define wxStyledTextCtrl_ClearDocumentStyle 2943
+#define wxStyledTextCtrl_GetLength 2944
+#define wxStyledTextCtrl_GetCharAt 2945
+#define wxStyledTextCtrl_GetCurrentPos 2946
+#define wxStyledTextCtrl_GetAnchor 2947
+#define wxStyledTextCtrl_GetStyleAt 2948
+#define wxStyledTextCtrl_Redo 2949
+#define wxStyledTextCtrl_SetUndoCollection 2950
+#define wxStyledTextCtrl_SelectAll 2951
+#define wxStyledTextCtrl_SetSavePoint 2952
+#define wxStyledTextCtrl_GetStyledText 2953
+#define wxStyledTextCtrl_CanRedo 2954
+#define wxStyledTextCtrl_MarkerLineFromHandle 2955
+#define wxStyledTextCtrl_MarkerDeleteHandle 2956
+#define wxStyledTextCtrl_GetUndoCollection 2957
+#define wxStyledTextCtrl_GetViewWhiteSpace 2958
+#define wxStyledTextCtrl_SetViewWhiteSpace 2959
+#define wxStyledTextCtrl_PositionFromPoint 2960
+#define wxStyledTextCtrl_PositionFromPointClose 2961
+#define wxStyledTextCtrl_GotoLine 2962
+#define wxStyledTextCtrl_GotoPos 2963
+#define wxStyledTextCtrl_SetAnchor 2964
+#define wxStyledTextCtrl_GetCurLine 2965
+#define wxStyledTextCtrl_GetEndStyled 2966
+#define wxStyledTextCtrl_ConvertEOLs 2967
+#define wxStyledTextCtrl_GetEOLMode 2968
+#define wxStyledTextCtrl_SetEOLMode 2969
+#define wxStyledTextCtrl_StartStyling 2970
+#define wxStyledTextCtrl_SetStyling 2971
+#define wxStyledTextCtrl_GetBufferedDraw 2972
+#define wxStyledTextCtrl_SetBufferedDraw 2973
+#define wxStyledTextCtrl_SetTabWidth 2974
+#define wxStyledTextCtrl_GetTabWidth 2975
+#define wxStyledTextCtrl_SetCodePage 2976
+#define wxStyledTextCtrl_MarkerDefine 2977
+#define wxStyledTextCtrl_MarkerSetForeground 2978
+#define wxStyledTextCtrl_MarkerSetBackground 2979
+#define wxStyledTextCtrl_MarkerAdd 2980
+#define wxStyledTextCtrl_MarkerDelete 2981
+#define wxStyledTextCtrl_MarkerDeleteAll 2982
+#define wxStyledTextCtrl_MarkerGet 2983
+#define wxStyledTextCtrl_MarkerNext 2984
+#define wxStyledTextCtrl_MarkerPrevious 2985
+#define wxStyledTextCtrl_MarkerDefineBitmap 2986
+#define wxStyledTextCtrl_MarkerAddSet 2987
+#define wxStyledTextCtrl_MarkerSetAlpha 2988
+#define wxStyledTextCtrl_SetMarginType 2989
+#define wxStyledTextCtrl_GetMarginType 2990
+#define wxStyledTextCtrl_SetMarginWidth 2991
+#define wxStyledTextCtrl_GetMarginWidth 2992
+#define wxStyledTextCtrl_SetMarginMask 2993
+#define wxStyledTextCtrl_GetMarginMask 2994
+#define wxStyledTextCtrl_SetMarginSensitive 2995
+#define wxStyledTextCtrl_GetMarginSensitive 2996
+#define wxStyledTextCtrl_StyleClearAll 2997
+#define wxStyledTextCtrl_StyleSetForeground 2998
+#define wxStyledTextCtrl_StyleSetBackground 2999
+#define wxStyledTextCtrl_StyleSetBold 3000
+#define wxStyledTextCtrl_StyleSetItalic 3001
+#define wxStyledTextCtrl_StyleSetSize 3002
+#define wxStyledTextCtrl_StyleSetFaceName 3003
+#define wxStyledTextCtrl_StyleSetEOLFilled 3004
+#define wxStyledTextCtrl_StyleResetDefault 3005
+#define wxStyledTextCtrl_StyleSetUnderline 3006
+#define wxStyledTextCtrl_StyleSetCase 3007
+#define wxStyledTextCtrl_StyleSetHotSpot 3008
+#define wxStyledTextCtrl_SetSelForeground 3009
+#define wxStyledTextCtrl_SetSelBackground 3010
+#define wxStyledTextCtrl_GetSelAlpha 3011
+#define wxStyledTextCtrl_SetSelAlpha 3012
+#define wxStyledTextCtrl_SetCaretForeground 3013
+#define wxStyledTextCtrl_CmdKeyAssign 3014
+#define wxStyledTextCtrl_CmdKeyClear 3015
+#define wxStyledTextCtrl_CmdKeyClearAll 3016
+#define wxStyledTextCtrl_SetStyleBytes 3017
+#define wxStyledTextCtrl_StyleSetVisible 3018
+#define wxStyledTextCtrl_GetCaretPeriod 3019
+#define wxStyledTextCtrl_SetCaretPeriod 3020
+#define wxStyledTextCtrl_SetWordChars 3021
+#define wxStyledTextCtrl_BeginUndoAction 3022
+#define wxStyledTextCtrl_EndUndoAction 3023
+#define wxStyledTextCtrl_IndicatorSetStyle 3024
+#define wxStyledTextCtrl_IndicatorGetStyle 3025
+#define wxStyledTextCtrl_IndicatorSetForeground 3026
+#define wxStyledTextCtrl_IndicatorGetForeground 3027
+#define wxStyledTextCtrl_SetWhitespaceForeground 3028
+#define wxStyledTextCtrl_SetWhitespaceBackground 3029
+#define wxStyledTextCtrl_GetStyleBits 3030
+#define wxStyledTextCtrl_SetLineState 3031
+#define wxStyledTextCtrl_GetLineState 3032
+#define wxStyledTextCtrl_GetMaxLineState 3033
+#define wxStyledTextCtrl_GetCaretLineVisible 3034
+#define wxStyledTextCtrl_SetCaretLineVisible 3035
+#define wxStyledTextCtrl_GetCaretLineBackground 3036
+#define wxStyledTextCtrl_SetCaretLineBackground 3037
+#define wxStyledTextCtrl_AutoCompShow 3038
+#define wxStyledTextCtrl_AutoCompCancel 3039
+#define wxStyledTextCtrl_AutoCompActive 3040
+#define wxStyledTextCtrl_AutoCompPosStart 3041
+#define wxStyledTextCtrl_AutoCompComplete 3042
+#define wxStyledTextCtrl_AutoCompStops 3043
+#define wxStyledTextCtrl_AutoCompSetSeparator 3044
+#define wxStyledTextCtrl_AutoCompGetSeparator 3045
+#define wxStyledTextCtrl_AutoCompSelect 3046
+#define wxStyledTextCtrl_AutoCompSetCancelAtStart 3047
+#define wxStyledTextCtrl_AutoCompGetCancelAtStart 3048
+#define wxStyledTextCtrl_AutoCompSetFillUps 3049
+#define wxStyledTextCtrl_AutoCompSetChooseSingle 3050
+#define wxStyledTextCtrl_AutoCompGetChooseSingle 3051
+#define wxStyledTextCtrl_AutoCompSetIgnoreCase 3052
+#define wxStyledTextCtrl_AutoCompGetIgnoreCase 3053
+#define wxStyledTextCtrl_UserListShow 3054
+#define wxStyledTextCtrl_AutoCompSetAutoHide 3055
+#define wxStyledTextCtrl_AutoCompGetAutoHide 3056
+#define wxStyledTextCtrl_AutoCompSetDropRestOfWord 3057
+#define wxStyledTextCtrl_AutoCompGetDropRestOfWord 3058
+#define wxStyledTextCtrl_RegisterImage 3059
+#define wxStyledTextCtrl_ClearRegisteredImages 3060
+#define wxStyledTextCtrl_AutoCompGetTypeSeparator 3061
+#define wxStyledTextCtrl_AutoCompSetTypeSeparator 3062
+#define wxStyledTextCtrl_AutoCompSetMaxWidth 3063
+#define wxStyledTextCtrl_AutoCompGetMaxWidth 3064
+#define wxStyledTextCtrl_AutoCompSetMaxHeight 3065
+#define wxStyledTextCtrl_AutoCompGetMaxHeight 3066
+#define wxStyledTextCtrl_SetIndent 3067
+#define wxStyledTextCtrl_GetIndent 3068
+#define wxStyledTextCtrl_SetUseTabs 3069
+#define wxStyledTextCtrl_GetUseTabs 3070
+#define wxStyledTextCtrl_SetLineIndentation 3071
+#define wxStyledTextCtrl_GetLineIndentation 3072
+#define wxStyledTextCtrl_GetLineIndentPosition 3073
+#define wxStyledTextCtrl_GetColumn 3074
+#define wxStyledTextCtrl_SetUseHorizontalScrollBar 3075
+#define wxStyledTextCtrl_GetUseHorizontalScrollBar 3076
+#define wxStyledTextCtrl_SetIndentationGuides 3077
+#define wxStyledTextCtrl_GetIndentationGuides 3078
+#define wxStyledTextCtrl_SetHighlightGuide 3079
+#define wxStyledTextCtrl_GetHighlightGuide 3080
+#define wxStyledTextCtrl_GetLineEndPosition 3081
+#define wxStyledTextCtrl_GetCodePage 3082
+#define wxStyledTextCtrl_GetCaretForeground 3083
+#define wxStyledTextCtrl_GetReadOnly 3084
+#define wxStyledTextCtrl_SetCurrentPos 3085
+#define wxStyledTextCtrl_SetSelectionStart 3086
+#define wxStyledTextCtrl_GetSelectionStart 3087
+#define wxStyledTextCtrl_SetSelectionEnd 3088
+#define wxStyledTextCtrl_GetSelectionEnd 3089
+#define wxStyledTextCtrl_SetPrintMagnification 3090
+#define wxStyledTextCtrl_GetPrintMagnification 3091
+#define wxStyledTextCtrl_SetPrintColourMode 3092
+#define wxStyledTextCtrl_GetPrintColourMode 3093
+#define wxStyledTextCtrl_FindText 3094
+#define wxStyledTextCtrl_FormatRange 3095
+#define wxStyledTextCtrl_GetFirstVisibleLine 3096
+#define wxStyledTextCtrl_GetLine 3097
+#define wxStyledTextCtrl_GetLineCount 3098
+#define wxStyledTextCtrl_SetMarginLeft 3099
+#define wxStyledTextCtrl_GetMarginLeft 3100
+#define wxStyledTextCtrl_SetMarginRight 3101
+#define wxStyledTextCtrl_GetMarginRight 3102
+#define wxStyledTextCtrl_GetModify 3103
+#define wxStyledTextCtrl_SetSelection 3104
+#define wxStyledTextCtrl_GetSelectedText 3105
+#define wxStyledTextCtrl_GetTextRange 3106
+#define wxStyledTextCtrl_HideSelection 3107
+#define wxStyledTextCtrl_LineFromPosition 3108
+#define wxStyledTextCtrl_PositionFromLine 3109
+#define wxStyledTextCtrl_LineScroll 3110
+#define wxStyledTextCtrl_EnsureCaretVisible 3111
+#define wxStyledTextCtrl_ReplaceSelection 3112
+#define wxStyledTextCtrl_SetReadOnly 3113
+#define wxStyledTextCtrl_CanPaste 3114
+#define wxStyledTextCtrl_CanUndo 3115
+#define wxStyledTextCtrl_EmptyUndoBuffer 3116
+#define wxStyledTextCtrl_Undo 3117
+#define wxStyledTextCtrl_Cut 3118
+#define wxStyledTextCtrl_Copy 3119
+#define wxStyledTextCtrl_Paste 3120
+#define wxStyledTextCtrl_Clear 3121
+#define wxStyledTextCtrl_SetText 3122
+#define wxStyledTextCtrl_GetText 3123
+#define wxStyledTextCtrl_GetTextLength 3124
+#define wxStyledTextCtrl_GetOvertype 3125
+#define wxStyledTextCtrl_SetCaretWidth 3126
+#define wxStyledTextCtrl_GetCaretWidth 3127
+#define wxStyledTextCtrl_SetTargetStart 3128
+#define wxStyledTextCtrl_GetTargetStart 3129
+#define wxStyledTextCtrl_SetTargetEnd 3130
+#define wxStyledTextCtrl_GetTargetEnd 3131
+#define wxStyledTextCtrl_ReplaceTarget 3132
+#define wxStyledTextCtrl_SearchInTarget 3133
+#define wxStyledTextCtrl_SetSearchFlags 3134
+#define wxStyledTextCtrl_GetSearchFlags 3135
+#define wxStyledTextCtrl_CallTipShow 3136
+#define wxStyledTextCtrl_CallTipCancel 3137
+#define wxStyledTextCtrl_CallTipActive 3138
+#define wxStyledTextCtrl_CallTipPosAtStart 3139
+#define wxStyledTextCtrl_CallTipSetHighlight 3140
+#define wxStyledTextCtrl_CallTipSetBackground 3141
+#define wxStyledTextCtrl_CallTipSetForeground 3142
+#define wxStyledTextCtrl_CallTipSetForegroundHighlight 3143
+#define wxStyledTextCtrl_CallTipUseStyle 3144
+#define wxStyledTextCtrl_VisibleFromDocLine 3145
+#define wxStyledTextCtrl_DocLineFromVisible 3146
+#define wxStyledTextCtrl_WrapCount 3147
+#define wxStyledTextCtrl_SetFoldLevel 3148
+#define wxStyledTextCtrl_GetFoldLevel 3149
+#define wxStyledTextCtrl_GetLastChild 3150
+#define wxStyledTextCtrl_GetFoldParent 3151
+#define wxStyledTextCtrl_ShowLines 3152
+#define wxStyledTextCtrl_HideLines 3153
+#define wxStyledTextCtrl_GetLineVisible 3154
+#define wxStyledTextCtrl_SetFoldExpanded 3155
+#define wxStyledTextCtrl_GetFoldExpanded 3156
+#define wxStyledTextCtrl_ToggleFold 3157
+#define wxStyledTextCtrl_EnsureVisible 3158
+#define wxStyledTextCtrl_SetFoldFlags 3159
+#define wxStyledTextCtrl_EnsureVisibleEnforcePolicy 3160
+#define wxStyledTextCtrl_SetTabIndents 3161
+#define wxStyledTextCtrl_GetTabIndents 3162
+#define wxStyledTextCtrl_SetBackSpaceUnIndents 3163
+#define wxStyledTextCtrl_GetBackSpaceUnIndents 3164
+#define wxStyledTextCtrl_SetMouseDwellTime 3165
+#define wxStyledTextCtrl_GetMouseDwellTime 3166
+#define wxStyledTextCtrl_WordStartPosition 3167
+#define wxStyledTextCtrl_WordEndPosition 3168
+#define wxStyledTextCtrl_SetWrapMode 3169
+#define wxStyledTextCtrl_GetWrapMode 3170
+#define wxStyledTextCtrl_SetWrapVisualFlags 3171
+#define wxStyledTextCtrl_GetWrapVisualFlags 3172
+#define wxStyledTextCtrl_SetWrapVisualFlagsLocation 3173
+#define wxStyledTextCtrl_GetWrapVisualFlagsLocation 3174
+#define wxStyledTextCtrl_SetWrapStartIndent 3175
+#define wxStyledTextCtrl_GetWrapStartIndent 3176
+#define wxStyledTextCtrl_SetLayoutCache 3177
+#define wxStyledTextCtrl_GetLayoutCache 3178
+#define wxStyledTextCtrl_SetScrollWidth 3179
+#define wxStyledTextCtrl_GetScrollWidth 3180
+#define wxStyledTextCtrl_TextWidth 3181
+#define wxStyledTextCtrl_GetEndAtLastLine 3182
+#define wxStyledTextCtrl_TextHeight 3183
+#define wxStyledTextCtrl_SetUseVerticalScrollBar 3184
+#define wxStyledTextCtrl_GetUseVerticalScrollBar 3185
+#define wxStyledTextCtrl_AppendText 3186
+#define wxStyledTextCtrl_GetTwoPhaseDraw 3187
+#define wxStyledTextCtrl_SetTwoPhaseDraw 3188
+#define wxStyledTextCtrl_TargetFromSelection 3189
+#define wxStyledTextCtrl_LinesJoin 3190
+#define wxStyledTextCtrl_LinesSplit 3191
+#define wxStyledTextCtrl_SetFoldMarginColour 3192
+#define wxStyledTextCtrl_SetFoldMarginHiColour 3193
+#define wxStyledTextCtrl_LineDown 3194
+#define wxStyledTextCtrl_LineDownExtend 3195
+#define wxStyledTextCtrl_LineUp 3196
+#define wxStyledTextCtrl_LineUpExtend 3197
+#define wxStyledTextCtrl_CharLeft 3198
+#define wxStyledTextCtrl_CharLeftExtend 3199
+#define wxStyledTextCtrl_CharRight 3200
+#define wxStyledTextCtrl_CharRightExtend 3201
+#define wxStyledTextCtrl_WordLeft 3202
+#define wxStyledTextCtrl_WordLeftExtend 3203
+#define wxStyledTextCtrl_WordRight 3204
+#define wxStyledTextCtrl_WordRightExtend 3205
+#define wxStyledTextCtrl_Home 3206
+#define wxStyledTextCtrl_HomeExtend 3207
+#define wxStyledTextCtrl_LineEnd 3208
+#define wxStyledTextCtrl_LineEndExtend 3209
+#define wxStyledTextCtrl_DocumentStart 3210
+#define wxStyledTextCtrl_DocumentStartExtend 3211
+#define wxStyledTextCtrl_DocumentEnd 3212
+#define wxStyledTextCtrl_DocumentEndExtend 3213
+#define wxStyledTextCtrl_PageUp 3214
+#define wxStyledTextCtrl_PageUpExtend 3215
+#define wxStyledTextCtrl_PageDown 3216
+#define wxStyledTextCtrl_PageDownExtend 3217
+#define wxStyledTextCtrl_EditToggleOvertype 3218
+#define wxStyledTextCtrl_Cancel 3219
+#define wxStyledTextCtrl_DeleteBack 3220
+#define wxStyledTextCtrl_Tab 3221
+#define wxStyledTextCtrl_BackTab 3222
+#define wxStyledTextCtrl_NewLine 3223
+#define wxStyledTextCtrl_FormFeed 3224
+#define wxStyledTextCtrl_VCHome 3225
+#define wxStyledTextCtrl_VCHomeExtend 3226
+#define wxStyledTextCtrl_ZoomIn 3227
+#define wxStyledTextCtrl_ZoomOut 3228
+#define wxStyledTextCtrl_DelWordLeft 3229
+#define wxStyledTextCtrl_DelWordRight 3230
+#define wxStyledTextCtrl_LineCut 3231
+#define wxStyledTextCtrl_LineDelete 3232
+#define wxStyledTextCtrl_LineTranspose 3233
+#define wxStyledTextCtrl_LineDuplicate 3234
+#define wxStyledTextCtrl_LowerCase 3235
+#define wxStyledTextCtrl_UpperCase 3236
+#define wxStyledTextCtrl_LineScrollDown 3237
+#define wxStyledTextCtrl_LineScrollUp 3238
+#define wxStyledTextCtrl_DeleteBackNotLine 3239
+#define wxStyledTextCtrl_HomeDisplay 3240
+#define wxStyledTextCtrl_HomeDisplayExtend 3241
+#define wxStyledTextCtrl_LineEndDisplay 3242
+#define wxStyledTextCtrl_LineEndDisplayExtend 3243
+#define wxStyledTextCtrl_HomeWrapExtend 3244
+#define wxStyledTextCtrl_LineEndWrap 3245
+#define wxStyledTextCtrl_LineEndWrapExtend 3246
+#define wxStyledTextCtrl_VCHomeWrap 3247
+#define wxStyledTextCtrl_VCHomeWrapExtend 3248
+#define wxStyledTextCtrl_LineCopy 3249
+#define wxStyledTextCtrl_MoveCaretInsideView 3250
+#define wxStyledTextCtrl_LineLength 3251
+#define wxStyledTextCtrl_BraceHighlight 3252
+#define wxStyledTextCtrl_BraceBadLight 3253
+#define wxStyledTextCtrl_BraceMatch 3254
+#define wxStyledTextCtrl_GetViewEOL 3255
+#define wxStyledTextCtrl_SetViewEOL 3256
+#define wxStyledTextCtrl_SetModEventMask 3257
+#define wxStyledTextCtrl_GetEdgeColumn 3258
+#define wxStyledTextCtrl_SetEdgeColumn 3259
+#define wxStyledTextCtrl_GetEdgeMode 3260
+#define wxStyledTextCtrl_GetEdgeColour 3261
+#define wxStyledTextCtrl_SetEdgeColour 3262
+#define wxStyledTextCtrl_SearchAnchor 3263
+#define wxStyledTextCtrl_SearchNext 3264
+#define wxStyledTextCtrl_SearchPrev 3265
+#define wxStyledTextCtrl_LinesOnScreen 3266
+#define wxStyledTextCtrl_UsePopUp 3267
+#define wxStyledTextCtrl_SelectionIsRectangle 3268
+#define wxStyledTextCtrl_SetZoom 3269
+#define wxStyledTextCtrl_GetZoom 3270
+#define wxStyledTextCtrl_GetModEventMask 3271
+#define wxStyledTextCtrl_SetSTCFocus 3272
+#define wxStyledTextCtrl_GetSTCFocus 3273
+#define wxStyledTextCtrl_SetStatus 3274
+#define wxStyledTextCtrl_GetStatus 3275
+#define wxStyledTextCtrl_SetMouseDownCaptures 3276
+#define wxStyledTextCtrl_GetMouseDownCaptures 3277
+#define wxStyledTextCtrl_SetSTCCursor 3278
+#define wxStyledTextCtrl_GetSTCCursor 3279
+#define wxStyledTextCtrl_SetControlCharSymbol 3280
+#define wxStyledTextCtrl_GetControlCharSymbol 3281
+#define wxStyledTextCtrl_WordPartLeft 3282
+#define wxStyledTextCtrl_WordPartLeftExtend 3283
+#define wxStyledTextCtrl_WordPartRight 3284
+#define wxStyledTextCtrl_WordPartRightExtend 3285
+#define wxStyledTextCtrl_SetVisiblePolicy 3286
+#define wxStyledTextCtrl_DelLineLeft 3287
+#define wxStyledTextCtrl_DelLineRight 3288
+#define wxStyledTextCtrl_GetXOffset 3289
+#define wxStyledTextCtrl_ChooseCaretX 3290
+#define wxStyledTextCtrl_SetXCaretPolicy 3291
+#define wxStyledTextCtrl_SetYCaretPolicy 3292
+#define wxStyledTextCtrl_GetPrintWrapMode 3293
+#define wxStyledTextCtrl_SetHotspotActiveForeground 3294
+#define wxStyledTextCtrl_SetHotspotActiveBackground 3295
+#define wxStyledTextCtrl_SetHotspotActiveUnderline 3296
+#define wxStyledTextCtrl_SetHotspotSingleLine 3297
+#define wxStyledTextCtrl_ParaDownExtend 3298
+#define wxStyledTextCtrl_ParaUp 3299
+#define wxStyledTextCtrl_ParaUpExtend 3300
+#define wxStyledTextCtrl_PositionBefore 3301
+#define wxStyledTextCtrl_PositionAfter 3302
+#define wxStyledTextCtrl_CopyRange 3303
+#define wxStyledTextCtrl_CopyText 3304
+#define wxStyledTextCtrl_SetSelectionMode 3305
+#define wxStyledTextCtrl_GetSelectionMode 3306
+#define wxStyledTextCtrl_LineDownRectExtend 3307
+#define wxStyledTextCtrl_LineUpRectExtend 3308
+#define wxStyledTextCtrl_CharLeftRectExtend 3309
+#define wxStyledTextCtrl_CharRightRectExtend 3310
+#define wxStyledTextCtrl_HomeRectExtend 3311
+#define wxStyledTextCtrl_VCHomeRectExtend 3312
+#define wxStyledTextCtrl_LineEndRectExtend 3313
+#define wxStyledTextCtrl_PageUpRectExtend 3314
+#define wxStyledTextCtrl_PageDownRectExtend 3315
+#define wxStyledTextCtrl_StutteredPageUp 3316
+#define wxStyledTextCtrl_StutteredPageUpExtend 3317
+#define wxStyledTextCtrl_StutteredPageDown 3318
+#define wxStyledTextCtrl_StutteredPageDownExtend 3319
+#define wxStyledTextCtrl_WordLeftEnd 3320
+#define wxStyledTextCtrl_WordLeftEndExtend 3321
+#define wxStyledTextCtrl_WordRightEnd 3322
+#define wxStyledTextCtrl_WordRightEndExtend 3323
+#define wxStyledTextCtrl_SetWhitespaceChars 3324
+#define wxStyledTextCtrl_SetCharsDefault 3325
+#define wxStyledTextCtrl_AutoCompGetCurrent 3326
+#define wxStyledTextCtrl_Allocate 3327
+#define wxStyledTextCtrl_FindColumn 3328
+#define wxStyledTextCtrl_GetCaretSticky 3329
+#define wxStyledTextCtrl_SetCaretSticky 3330
+#define wxStyledTextCtrl_ToggleCaretSticky 3331
+#define wxStyledTextCtrl_SetPasteConvertEndings 3332
+#define wxStyledTextCtrl_GetPasteConvertEndings 3333
+#define wxStyledTextCtrl_SelectionDuplicate 3334
+#define wxStyledTextCtrl_SetCaretLineBackAlpha 3335
+#define wxStyledTextCtrl_GetCaretLineBackAlpha 3336
+#define wxStyledTextCtrl_StartRecord 3337
+#define wxStyledTextCtrl_StopRecord 3338
+#define wxStyledTextCtrl_SetLexer 3339
+#define wxStyledTextCtrl_GetLexer 3340
+#define wxStyledTextCtrl_Colourise 3341
+#define wxStyledTextCtrl_SetProperty 3342
+#define wxStyledTextCtrl_SetKeyWords 3343
+#define wxStyledTextCtrl_SetLexerLanguage 3344
+#define wxStyledTextCtrl_GetProperty 3345
+#define wxStyledTextCtrl_GetStyleBitsNeeded 3346
+#define wxStyledTextCtrl_GetCurrentLine 3347
+#define wxStyledTextCtrl_StyleSetSpec 3348
+#define wxStyledTextCtrl_StyleSetFont 3349
+#define wxStyledTextCtrl_StyleSetFontAttr 3350
+#define wxStyledTextCtrl_StyleSetCharacterSet 3351
+#define wxStyledTextCtrl_StyleSetFontEncoding 3352
+#define wxStyledTextCtrl_CmdKeyExecute 3353
+#define wxStyledTextCtrl_SetMargins 3354
+#define wxStyledTextCtrl_GetSelection 3355
+#define wxStyledTextCtrl_PointFromPosition 3356
+#define wxStyledTextCtrl_ScrollToLine 3357
+#define wxStyledTextCtrl_ScrollToColumn 3358
+#define wxStyledTextCtrl_SendMsg 3359
+#define wxStyledTextCtrl_SetVScrollBar 3360
+#define wxStyledTextCtrl_SetHScrollBar 3361
+#define wxStyledTextCtrl_GetLastKeydownProcessed 3362
+#define wxStyledTextCtrl_SetLastKeydownProcessed 3363
+#define wxStyledTextCtrl_SaveFile 3364
+#define wxStyledTextCtrl_LoadFile 3365
+#define wxStyledTextCtrl_DoDragOver 3366
+#define wxStyledTextCtrl_DoDropText 3367
+#define wxStyledTextCtrl_GetUseAntiAliasing 3368
+#define wxStyledTextCtrl_AddTextRaw 3369
+#define wxStyledTextCtrl_InsertTextRaw 3370
+#define wxStyledTextCtrl_GetCurLineRaw 3371
+#define wxStyledTextCtrl_GetLineRaw 3372
+#define wxStyledTextCtrl_GetSelectedTextRaw 3373
+#define wxStyledTextCtrl_GetTextRangeRaw 3374
+#define wxStyledTextCtrl_SetTextRaw 3375
+#define wxStyledTextCtrl_GetTextRaw 3376
+#define wxStyledTextCtrl_AppendTextRaw 3377
+#define wxArtProvider_GetBitmap 3378
+#define wxArtProvider_GetIcon 3379
+#define wxTreeEvent_GetKeyCode 3380
+#define wxTreeEvent_GetItem 3381
+#define wxTreeEvent_GetKeyEvent 3382
+#define wxTreeEvent_GetLabel 3383
+#define wxTreeEvent_GetOldItem 3384
+#define wxTreeEvent_GetPoint 3385
+#define wxTreeEvent_IsEditCancelled 3386
+#define wxTreeEvent_SetToolTip 3387
+#define wxNotebookEvent_GetOldSelection 3388
+#define wxNotebookEvent_GetSelection 3389
+#define wxNotebookEvent_SetOldSelection 3390
+#define wxNotebookEvent_SetSelection 3391
+#define wxFileDataObject_new 3392
+#define wxFileDataObject_AddFile 3393
+#define wxFileDataObject_GetFilenames 3394
+#define wxFileDataObject_destroy 3395
+#define wxTextDataObject_new 3396
+#define wxTextDataObject_GetTextLength 3397
+#define wxTextDataObject_GetText 3398
+#define wxTextDataObject_SetText 3399
+#define wxTextDataObject_destroy 3400
+#define wxBitmapDataObject_new_1_1 3401
+#define wxBitmapDataObject_new_1_0 3402
+#define wxBitmapDataObject_GetBitmap 3403
+#define wxBitmapDataObject_SetBitmap 3404
+#define wxBitmapDataObject_destroy 3405
+#define wxClipboard_new 3407
+#define wxClipboard_destruct 3408
+#define wxClipboard_AddData 3409
+#define wxClipboard_Clear 3410
+#define wxClipboard_Close 3411
+#define wxClipboard_Flush 3412
+#define wxClipboard_GetData 3413
+#define wxClipboard_IsOpened 3414
+#define wxClipboard_Open 3415
+#define wxClipboard_SetData 3416
+#define wxClipboard_UsePrimarySelection 3418
+#define wxClipboard_IsSupported 3419
+#define wxClipboard_Get 3420
+#define wxSpinEvent_GetPosition 3421
+#define wxSpinEvent_SetPosition 3422
+#define wxSplitterWindow_new_0 3423
+#define wxSplitterWindow_new_2 3424
+#define wxSplitterWindow_destruct 3425
+#define wxSplitterWindow_Create 3426
+#define wxSplitterWindow_GetMinimumPaneSize 3427
+#define wxSplitterWindow_GetSashGravity 3428
+#define wxSplitterWindow_GetSashPosition 3429
+#define wxSplitterWindow_GetSplitMode 3430
+#define wxSplitterWindow_GetWindow1 3431
+#define wxSplitterWindow_GetWindow2 3432
+#define wxSplitterWindow_Initialize 3433
+#define wxSplitterWindow_IsSplit 3434
+#define wxSplitterWindow_ReplaceWindow 3435
+#define wxSplitterWindow_SetSashGravity 3436
+#define wxSplitterWindow_SetSashPosition 3437
+#define wxSplitterWindow_SetSashSize 3438
+#define wxSplitterWindow_SetMinimumPaneSize 3439
+#define wxSplitterWindow_SetSplitMode 3440
+#define wxSplitterWindow_SplitHorizontally 3441
+#define wxSplitterWindow_SplitVertically 3442
+#define wxSplitterWindow_Unsplit 3443
+#define wxSplitterWindow_UpdateSize 3444
+#define wxSplitterEvent_GetSashPosition 3445
+#define wxSplitterEvent_GetX 3446
+#define wxSplitterEvent_GetY 3447
+#define wxSplitterEvent_GetWindowBeingRemoved 3448
+#define wxSplitterEvent_SetSashPosition 3449
+#define wxHtmlWindow_new_0 3450
+#define wxHtmlWindow_new_2 3451
+#define wxHtmlWindow_AppendToPage 3452
+#define wxHtmlWindow_GetOpenedAnchor 3453
+#define wxHtmlWindow_GetOpenedPage 3454
+#define wxHtmlWindow_GetOpenedPageTitle 3455
+#define wxHtmlWindow_GetRelatedFrame 3456
+#define wxHtmlWindow_HistoryBack 3457
+#define wxHtmlWindow_HistoryCanBack 3458
+#define wxHtmlWindow_HistoryCanForward 3459
+#define wxHtmlWindow_HistoryClear 3460
+#define wxHtmlWindow_HistoryForward 3461
+#define wxHtmlWindow_LoadFile 3462
+#define wxHtmlWindow_LoadPage 3463
+#define wxHtmlWindow_SelectAll 3464
+#define wxHtmlWindow_SelectionToText 3465
+#define wxHtmlWindow_SelectLine 3466
+#define wxHtmlWindow_SelectWord 3467
+#define wxHtmlWindow_SetBorders 3468
+#define wxHtmlWindow_SetFonts 3469
+#define wxHtmlWindow_SetPage 3470
+#define wxHtmlWindow_SetRelatedFrame 3471
+#define wxHtmlWindow_SetRelatedStatusBar 3472
+#define wxHtmlWindow_ToText 3473
+#define wxHtmlWindow_destroy 3474
+#define wxHtmlLinkEvent_GetLinkInfo 3475
+#define wxSystemSettings_GetColour 3476
+#define wxSystemSettings_GetFont 3477
+#define wxSystemSettings_GetMetric 3478
+#define wxSystemSettings_GetScreenType 3479
+#define wxAuiNotebookEvent_SetSelection 3480
+#define wxAuiNotebookEvent_GetSelection 3481
+#define wxAuiNotebookEvent_SetOldSelection 3482
+#define wxAuiNotebookEvent_GetOldSelection 3483
+#define wxAuiNotebookEvent_SetDragSource 3484
+#define wxAuiNotebookEvent_GetDragSource 3485
+#define wxAuiManagerEvent_SetManager 3486
+#define wxAuiManagerEvent_GetManager 3487
+#define wxAuiManagerEvent_SetPane 3488
+#define wxAuiManagerEvent_GetPane 3489
+#define wxAuiManagerEvent_SetButton 3490
+#define wxAuiManagerEvent_GetButton 3491
+#define wxAuiManagerEvent_SetDC 3492
+#define wxAuiManagerEvent_GetDC 3493
+#define wxAuiManagerEvent_Veto 3494
+#define wxAuiManagerEvent_GetVeto 3495
+#define wxAuiManagerEvent_SetCanVeto 3496
+#define wxAuiManagerEvent_CanVeto 3497
+#define wxLogNull_new 3498
+#define wxLogNull_destroy 3499
diff --git a/lib/wx/c_src/wxe_impl.cpp b/lib/wx/c_src/wxe_impl.cpp
index 528a08e654..6d2926ce4e 100644
--- a/lib/wx/c_src/wxe_impl.cpp
+++ b/lib/wx/c_src/wxe_impl.cpp
@@ -411,7 +411,7 @@ void WxeApp::dispatch_cb(wxList * batch, wxList * temp, ErlDrvTermData process)
if(event->caller == process || // Callbacks from CB process only
event->op == WXE_CB_START || // Recursive event callback allow
// Allow connect_cb during CB i.e. msg from wxe_server.
- event->caller == memenv->owner)
+ (memenv && event->caller == memenv->owner))
{
switch(event->op) {
case WXE_BATCH_END:
@@ -669,7 +669,7 @@ void WxeApp::clearPtr(void * ptr) {
send_msg("debug", &msg);
}
- if(refd->pid != -1) {
+ if(((int) refd->pid) != -1) {
// Send terminate pid to owner
wxeReturn rt = wxeReturn(WXE_DRV_PORT,refd->memenv->owner, false);
rt.addAtom("_wxe_destroy_");
diff --git a/lib/wx/configure.in b/lib/wx/configure.in
index 855c0c975e..8f8c5ee123 100755
--- a/lib/wx/configure.in
+++ b/lib/wx/configure.in
@@ -194,6 +194,36 @@ case $host_os in
;;
esac
+dnl
+dnl Opengl tests
+dnl
+
+if test X"$host_os" != X"win32" ; then
+ AC_CHECK_HEADERS([GL/gl.h], [],
+ [AC_CHECK_HEADERS([OpenGL/gl.h])])
+ if test X"$ac_cv_header_GL_gl_h" != Xyes &&
+ test X"$ac_cv_header_OpenGL_gl_h" != Xyes
+ then
+ saved_CPPFLAGS="$CPPFLAGS"
+ AC_MSG_NOTICE(Checking for OpenGL headers in /usr/X11R6)
+ CPPFLAGS="-isystem /usr/X11R6/include $CPPFLAGS"
+ $as_unset ac_cv_header_GL_gl_h
+ AC_CHECK_HEADERS([GL/gl.h])
+ if test X"$ac_cv_header_GL_gl_h" != Xyes ; then
+ AC_MSG_NOTICE(Checking for OpenGL headers in /usr/local)
+ CPPFLAGS="-isystem /usr/local/include $saved_CPPFLAGS"
+ $as_unset ac_cv_header_GL_gl_h
+ AC_CHECK_HEADERS([GL/gl.h])
+ if test X"$ac_cv_header_GL_gl_h" != Xyes ; then
+ AC_MSG_WARN([No OpenGL headers found, wx will NOT be usable])
+ CPPFLAGS="$saved_CPPFLAGS"
+ fi
+ fi
+ fi
+else
+ AC_CHECK_HEADERS([gl/gl.h],[],[],[#include <windows.h>])
+fi
+
CXXFLAGS="$CFLAGS $CPPFLAGS"
CFLAGS="$CFLAGS $CPPFLAGS $C_ONLY_FLAGS"
@@ -386,17 +416,6 @@ if test "$WXERL_CAN_BUILD_DRIVER" != "false"; then
AC_SUBST(WX_HAVE_STATIC_LIBS)
AC_SUBST(RC_FILE_TYPE)
-dnl
-dnl Opengl tests
-dnl
-
-if test X"$host_os" != X"win32" ; then
- AC_CHECK_HEADERS([GL/gl.h])
- AC_CHECK_HEADERS([OpenGL/gl.h])
-else
- AC_CHECK_HEADERS([gl/gl.h],[],[],[#include <windows.h>])
-fi
-
AC_MSG_CHECKING(if wxwidgets have opengl support)
AC_LANG_PUSH(C++)
saved_CXXFLAGS=$CXXFLAGS
diff --git a/lib/wx/doc/src/notes.xml b/lib/wx/doc/src/notes.xml
index 34c56091aa..8414028106 100644
--- a/lib/wx/doc/src/notes.xml
+++ b/lib/wx/doc/src/notes.xml
@@ -31,6 +31,35 @@
<p>This document describes the changes made to the wxErlang
application.</p>
+<section><title>Wx 0.98.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix crash (segmentation fault) in callback handling.</p>
+ <p>
+ Own Id: OTP-8766</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Add wxSystemSettings module.</p>
+ <p>
+ Add wxTreeCtrl:editLabel/2.</p>
+ <p>
+ Own Id: OTP-8767</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Wx 0.98.6</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/wx/src/gen/wxTreeCtrl.erl b/lib/wx/src/gen/wxTreeCtrl.erl
index 4fcbb9366e..e3fe4c9612 100644
--- a/lib/wx/src/gen/wxTreeCtrl.erl
+++ b/lib/wx/src/gen/wxTreeCtrl.erl
@@ -35,7 +35,7 @@
-include("wxe.hrl").
-export([addRoot/2,addRoot/3,appendItem/3,appendItem/4,assignImageList/2,assignStateImageList/2,
collapse/2,collapseAndReset/2,create/2,create/3,delete/2,deleteAllItems/1,
- deleteChildren/2,destroy/1,ensureVisible/2,expand/2,getBoundingRect/3,
+ deleteChildren/2,destroy/1,editLabel/2,ensureVisible/2,expand/2,getBoundingRect/3,
getBoundingRect/4,getChildrenCount/2,getChildrenCount/3,getCount/1,
getEditControl/1,getFirstChild/2,getFirstVisibleItem/1,getImageList/1,
getIndent/1,getItemBackgroundColour/2,getItemData/2,getItemFont/2,
@@ -243,6 +243,14 @@ deleteChildren(#wx_ref{type=ThisT,ref=ThisRef},Item)
wxe_util:cast(?wxTreeCtrl_DeleteChildren,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
+%% @spec (This::wxTreeCtrl(), Item::integer()) -> wxTextCtrl:wxTextCtrl()
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrleditlabel">external documentation</a>.
+editLabel(#wx_ref{type=ThisT,ref=ThisRef},Item)
+ when is_integer(Item) ->
+ ?CLASS(ThisT,wxTreeCtrl),
+ wxe_util:call(?wxTreeCtrl_EditLabel,
+ <<ThisRef:32/?UI,0:32,Item:64/?UI>>).
+
%% @spec (This::wxTreeCtrl(), Item::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlensurevisible">external documentation</a>.
ensureVisible(#wx_ref{type=ThisT,ref=ThisRef},Item)
diff --git a/lib/wx/src/gen/wxe_debug.hrl b/lib/wx/src/gen/wxe_debug.hrl
index a3416b75c8..3edfa73599 100644
--- a/lib/wx/src/gen/wxe_debug.hrl
+++ b/lib/wx/src/gen/wxe_debug.hrl
@@ -1837,1445 +1837,1450 @@ wxdebug_table() ->
{2007, {wxTreeCtrl, delete, 1}},
{2008, {wxTreeCtrl, deleteAllItems, 0}},
{2009, {wxTreeCtrl, deleteChildren, 1}},
- {2010, {wxTreeCtrl, ensureVisible, 1}},
- {2011, {wxTreeCtrl, expand, 1}},
- {2012, {wxTreeCtrl, getBoundingRect, 3}},
- {2014, {wxTreeCtrl, getChildrenCount, 2}},
- {2015, {wxTreeCtrl, getCount, 0}},
- {2016, {wxTreeCtrl, getEditControl, 0}},
- {2017, {wxTreeCtrl, getFirstChild, 2}},
- {2018, {wxTreeCtrl, getNextChild, 2}},
- {2019, {wxTreeCtrl, getFirstVisibleItem, 0}},
- {2020, {wxTreeCtrl, getImageList, 0}},
- {2021, {wxTreeCtrl, getIndent, 0}},
- {2022, {wxTreeCtrl, getItemBackgroundColour, 1}},
- {2023, {wxTreeCtrl, getItemData, 1}},
- {2024, {wxTreeCtrl, getItemFont, 1}},
- {2025, {wxTreeCtrl, getItemImage_1, 1}},
- {2026, {wxTreeCtrl, getItemImage_2, 2}},
- {2027, {wxTreeCtrl, getItemText, 1}},
- {2028, {wxTreeCtrl, getItemTextColour, 1}},
- {2029, {wxTreeCtrl, getLastChild, 1}},
- {2030, {wxTreeCtrl, getNextSibling, 1}},
- {2031, {wxTreeCtrl, getNextVisible, 1}},
- {2032, {wxTreeCtrl, getItemParent, 1}},
- {2033, {wxTreeCtrl, getPrevSibling, 1}},
- {2034, {wxTreeCtrl, getPrevVisible, 1}},
- {2035, {wxTreeCtrl, getRootItem, 0}},
- {2036, {wxTreeCtrl, getSelection, 0}},
- {2037, {wxTreeCtrl, getSelections, 1}},
- {2038, {wxTreeCtrl, getStateImageList, 0}},
- {2039, {wxTreeCtrl, hitTest, 1}},
- {2041, {wxTreeCtrl, insertItem, 4}},
- {2042, {wxTreeCtrl, isBold, 1}},
- {2043, {wxTreeCtrl, isExpanded, 1}},
- {2044, {wxTreeCtrl, isSelected, 1}},
- {2045, {wxTreeCtrl, isVisible, 1}},
- {2046, {wxTreeCtrl, itemHasChildren, 1}},
- {2047, {wxTreeCtrl, prependItem, 3}},
- {2048, {wxTreeCtrl, scrollTo, 1}},
- {2049, {wxTreeCtrl, selectItem_1, 1}},
- {2050, {wxTreeCtrl, selectItem_2, 2}},
- {2051, {wxTreeCtrl, setIndent, 1}},
- {2052, {wxTreeCtrl, setImageList, 1}},
- {2053, {wxTreeCtrl, setItemBackgroundColour, 2}},
- {2054, {wxTreeCtrl, setItemBold, 2}},
- {2055, {wxTreeCtrl, setItemData, 2}},
- {2056, {wxTreeCtrl, setItemDropHighlight, 2}},
- {2057, {wxTreeCtrl, setItemFont, 2}},
- {2058, {wxTreeCtrl, setItemHasChildren, 2}},
- {2059, {wxTreeCtrl, setItemImage_2, 2}},
- {2060, {wxTreeCtrl, setItemImage_3, 3}},
- {2061, {wxTreeCtrl, setItemText, 2}},
- {2062, {wxTreeCtrl, setItemTextColour, 2}},
- {2063, {wxTreeCtrl, setStateImageList, 1}},
- {2064, {wxTreeCtrl, setWindowStyle, 1}},
- {2065, {wxTreeCtrl, sortChildren, 1}},
- {2066, {wxTreeCtrl, toggle, 1}},
- {2067, {wxTreeCtrl, toggleItemSelection, 1}},
- {2068, {wxTreeCtrl, unselect, 0}},
- {2069, {wxTreeCtrl, unselectAll, 0}},
- {2070, {wxTreeCtrl, unselectItem, 1}},
- {2071, {wxScrollBar, new_0, 0}},
- {2072, {wxScrollBar, new_3, 3}},
- {2073, {wxScrollBar, destruct, 0}},
- {2074, {wxScrollBar, create, 3}},
- {2075, {wxScrollBar, getRange, 0}},
- {2076, {wxScrollBar, getPageSize, 0}},
- {2077, {wxScrollBar, getThumbPosition, 0}},
- {2078, {wxScrollBar, getThumbSize, 0}},
- {2079, {wxScrollBar, setThumbPosition, 1}},
- {2080, {wxScrollBar, setScrollbar, 5}},
- {2082, {wxSpinButton, new_2, 2}},
- {2083, {wxSpinButton, new_0, 0}},
- {2084, {wxSpinButton, create, 2}},
- {2085, {wxSpinButton, getMax, 0}},
- {2086, {wxSpinButton, getMin, 0}},
- {2087, {wxSpinButton, getValue, 0}},
- {2088, {wxSpinButton, setRange, 2}},
- {2089, {wxSpinButton, setValue, 1}},
- {2090, {wxSpinButton, 'Destroy', undefined}},
- {2091, {wxSpinCtrl, new_0, 0}},
- {2092, {wxSpinCtrl, new_2, 2}},
- {2094, {wxSpinCtrl, create, 2}},
- {2097, {wxSpinCtrl, setValue_1_1, 1}},
- {2098, {wxSpinCtrl, setValue_1_0, 1}},
- {2100, {wxSpinCtrl, getValue, 0}},
- {2102, {wxSpinCtrl, setRange, 2}},
- {2103, {wxSpinCtrl, setSelection, 2}},
- {2105, {wxSpinCtrl, getMin, 0}},
- {2107, {wxSpinCtrl, getMax, 0}},
- {2108, {wxSpinCtrl, 'Destroy', undefined}},
- {2109, {wxStaticText, new_0, 0}},
- {2110, {wxStaticText, new_4, 4}},
- {2111, {wxStaticText, create, 4}},
- {2112, {wxStaticText, getLabel, 0}},
- {2113, {wxStaticText, setLabel, 1}},
- {2114, {wxStaticText, wrap, 1}},
- {2115, {wxStaticText, 'Destroy', undefined}},
- {2116, {wxStaticBitmap, new_0, 0}},
- {2117, {wxStaticBitmap, new_4, 4}},
- {2118, {wxStaticBitmap, create, 4}},
- {2119, {wxStaticBitmap, getBitmap, 0}},
- {2120, {wxStaticBitmap, setBitmap, 1}},
- {2121, {wxStaticBitmap, 'Destroy', undefined}},
- {2122, {wxRadioBox, new, 7}},
- {2124, {wxRadioBox, destruct, 0}},
- {2125, {wxRadioBox, create, 7}},
- {2126, {wxRadioBox, enable_2, 2}},
- {2127, {wxRadioBox, enable_1, 1}},
- {2128, {wxRadioBox, getSelection, 0}},
- {2129, {wxRadioBox, getString, 1}},
- {2130, {wxRadioBox, setSelection, 1}},
- {2131, {wxRadioBox, show_2, 2}},
- {2132, {wxRadioBox, show_1, 1}},
- {2133, {wxRadioBox, getColumnCount, 0}},
- {2134, {wxRadioBox, getItemHelpText, 1}},
- {2135, {wxRadioBox, getItemToolTip, 1}},
- {2137, {wxRadioBox, getItemFromPoint, 1}},
- {2138, {wxRadioBox, getRowCount, 0}},
- {2139, {wxRadioBox, isItemEnabled, 1}},
- {2140, {wxRadioBox, isItemShown, 1}},
- {2141, {wxRadioBox, setItemHelpText, 2}},
- {2142, {wxRadioBox, setItemToolTip, 2}},
- {2143, {wxRadioButton, new_0, 0}},
- {2144, {wxRadioButton, new_4, 4}},
- {2145, {wxRadioButton, create, 4}},
- {2146, {wxRadioButton, getValue, 0}},
- {2147, {wxRadioButton, setValue, 1}},
- {2148, {wxRadioButton, 'Destroy', undefined}},
- {2150, {wxSlider, new_6, 6}},
- {2151, {wxSlider, new_0, 0}},
- {2152, {wxSlider, create, 6}},
- {2153, {wxSlider, getLineSize, 0}},
- {2154, {wxSlider, getMax, 0}},
- {2155, {wxSlider, getMin, 0}},
- {2156, {wxSlider, getPageSize, 0}},
- {2157, {wxSlider, getThumbLength, 0}},
- {2158, {wxSlider, getValue, 0}},
- {2159, {wxSlider, setLineSize, 1}},
- {2160, {wxSlider, setPageSize, 1}},
- {2161, {wxSlider, setRange, 2}},
- {2162, {wxSlider, setThumbLength, 1}},
- {2163, {wxSlider, setValue, 1}},
- {2164, {wxSlider, 'Destroy', undefined}},
- {2166, {wxDialog, new_4, 4}},
- {2167, {wxDialog, new_0, 0}},
- {2169, {wxDialog, destruct, 0}},
- {2170, {wxDialog, create, 4}},
- {2171, {wxDialog, createButtonSizer, 1}},
- {2172, {wxDialog, createStdDialogButtonSizer, 1}},
- {2173, {wxDialog, endModal, 1}},
- {2174, {wxDialog, getAffirmativeId, 0}},
- {2175, {wxDialog, getReturnCode, 0}},
- {2176, {wxDialog, isModal, 0}},
- {2177, {wxDialog, setAffirmativeId, 1}},
- {2178, {wxDialog, setReturnCode, 1}},
- {2179, {wxDialog, show, 1}},
- {2180, {wxDialog, showModal, 0}},
- {2181, {wxColourDialog, new_0, 0}},
- {2182, {wxColourDialog, new_2, 2}},
- {2183, {wxColourDialog, destruct, 0}},
- {2184, {wxColourDialog, create, 2}},
- {2185, {wxColourDialog, getColourData, 0}},
- {2186, {wxColourData, new_0, 0}},
- {2187, {wxColourData, new_1, 1}},
- {2188, {wxColourData, destruct, 0}},
- {2189, {wxColourData, getChooseFull, 0}},
- {2190, {wxColourData, getColour, 0}},
- {2192, {wxColourData, getCustomColour, 1}},
- {2193, {wxColourData, setChooseFull, 1}},
- {2194, {wxColourData, setColour, 1}},
- {2195, {wxColourData, setCustomColour, 2}},
- {2196, {wxPalette, new_0, 0}},
- {2197, {wxPalette, new_4, 4}},
- {2199, {wxPalette, destruct, 0}},
- {2200, {wxPalette, create, 4}},
- {2201, {wxPalette, getColoursCount, 0}},
- {2202, {wxPalette, getPixel, 3}},
- {2203, {wxPalette, getRGB, 4}},
- {2204, {wxPalette, isOk, 0}},
- {2208, {wxDirDialog, new, 2}},
- {2209, {wxDirDialog, destruct, 0}},
- {2210, {wxDirDialog, getPath, 0}},
- {2211, {wxDirDialog, getMessage, 0}},
- {2212, {wxDirDialog, setMessage, 1}},
- {2213, {wxDirDialog, setPath, 1}},
- {2217, {wxFileDialog, new, 2}},
- {2218, {wxFileDialog, destruct, 0}},
- {2219, {wxFileDialog, getDirectory, 0}},
- {2220, {wxFileDialog, getFilename, 0}},
- {2221, {wxFileDialog, getFilenames, 1}},
- {2222, {wxFileDialog, getFilterIndex, 0}},
- {2223, {wxFileDialog, getMessage, 0}},
- {2224, {wxFileDialog, getPath, 0}},
- {2225, {wxFileDialog, getPaths, 1}},
- {2226, {wxFileDialog, getWildcard, 0}},
- {2227, {wxFileDialog, setDirectory, 1}},
- {2228, {wxFileDialog, setFilename, 1}},
- {2229, {wxFileDialog, setFilterIndex, 1}},
- {2230, {wxFileDialog, setMessage, 1}},
- {2231, {wxFileDialog, setPath, 1}},
- {2232, {wxFileDialog, setWildcard, 1}},
- {2233, {wxPickerBase, setInternalMargin, 1}},
- {2234, {wxPickerBase, getInternalMargin, 0}},
- {2235, {wxPickerBase, setTextCtrlProportion, 1}},
- {2236, {wxPickerBase, setPickerCtrlProportion, 1}},
- {2237, {wxPickerBase, getTextCtrlProportion, 0}},
- {2238, {wxPickerBase, getPickerCtrlProportion, 0}},
- {2239, {wxPickerBase, hasTextCtrl, 0}},
- {2240, {wxPickerBase, getTextCtrl, 0}},
- {2241, {wxPickerBase, isTextCtrlGrowable, 0}},
- {2242, {wxPickerBase, setPickerCtrlGrowable, 1}},
- {2243, {wxPickerBase, setTextCtrlGrowable, 1}},
- {2244, {wxPickerBase, isPickerCtrlGrowable, 0}},
- {2245, {wxFilePickerCtrl, new_0, 0}},
- {2246, {wxFilePickerCtrl, new_3, 3}},
- {2247, {wxFilePickerCtrl, create, 3}},
- {2248, {wxFilePickerCtrl, getPath, 0}},
- {2249, {wxFilePickerCtrl, setPath, 1}},
- {2250, {wxFilePickerCtrl, 'Destroy', undefined}},
- {2251, {wxDirPickerCtrl, new_0, 0}},
- {2252, {wxDirPickerCtrl, new_3, 3}},
- {2253, {wxDirPickerCtrl, create, 3}},
- {2254, {wxDirPickerCtrl, getPath, 0}},
- {2255, {wxDirPickerCtrl, setPath, 1}},
- {2256, {wxDirPickerCtrl, 'Destroy', undefined}},
- {2257, {wxColourPickerCtrl, new_0, 0}},
- {2258, {wxColourPickerCtrl, new_3, 3}},
- {2259, {wxColourPickerCtrl, create, 3}},
- {2260, {wxColourPickerCtrl, getColour, 0}},
- {2261, {wxColourPickerCtrl, setColour_1_1, 1}},
- {2262, {wxColourPickerCtrl, setColour_1_0, 1}},
- {2263, {wxColourPickerCtrl, 'Destroy', undefined}},
- {2264, {wxDatePickerCtrl, new_0, 0}},
- {2265, {wxDatePickerCtrl, new_3, 3}},
- {2266, {wxDatePickerCtrl, getRange, 2}},
- {2267, {wxDatePickerCtrl, getValue, 0}},
- {2268, {wxDatePickerCtrl, setRange, 2}},
- {2269, {wxDatePickerCtrl, setValue, 1}},
- {2270, {wxDatePickerCtrl, 'Destroy', undefined}},
- {2271, {wxFontPickerCtrl, new_0, 0}},
- {2272, {wxFontPickerCtrl, new_3, 3}},
- {2273, {wxFontPickerCtrl, create, 3}},
- {2274, {wxFontPickerCtrl, getSelectedFont, 0}},
- {2275, {wxFontPickerCtrl, setSelectedFont, 1}},
- {2276, {wxFontPickerCtrl, getMaxPointSize, 0}},
- {2277, {wxFontPickerCtrl, setMaxPointSize, 1}},
- {2278, {wxFontPickerCtrl, 'Destroy', undefined}},
- {2281, {wxFindReplaceDialog, new_0, 0}},
- {2282, {wxFindReplaceDialog, new_4, 4}},
- {2283, {wxFindReplaceDialog, destruct, 0}},
- {2284, {wxFindReplaceDialog, create, 4}},
- {2285, {wxFindReplaceDialog, getData, 0}},
- {2286, {wxFindReplaceData, new_0, 0}},
- {2287, {wxFindReplaceData, new_1, 1}},
- {2288, {wxFindReplaceData, getFindString, 0}},
- {2289, {wxFindReplaceData, getReplaceString, 0}},
- {2290, {wxFindReplaceData, getFlags, 0}},
- {2291, {wxFindReplaceData, setFlags, 1}},
- {2292, {wxFindReplaceData, setFindString, 1}},
- {2293, {wxFindReplaceData, setReplaceString, 1}},
- {2294, {wxFindReplaceData, 'Destroy', undefined}},
- {2295, {wxMultiChoiceDialog, new_0, 0}},
- {2297, {wxMultiChoiceDialog, new_5, 5}},
- {2298, {wxMultiChoiceDialog, getSelections, 0}},
- {2299, {wxMultiChoiceDialog, setSelections, 1}},
- {2300, {wxMultiChoiceDialog, 'Destroy', undefined}},
- {2301, {wxSingleChoiceDialog, new_0, 0}},
- {2303, {wxSingleChoiceDialog, new_5, 5}},
- {2304, {wxSingleChoiceDialog, getSelection, 0}},
- {2305, {wxSingleChoiceDialog, getStringSelection, 0}},
- {2306, {wxSingleChoiceDialog, setSelection, 1}},
- {2307, {wxSingleChoiceDialog, 'Destroy', undefined}},
- {2308, {wxTextEntryDialog, new, 3}},
- {2309, {wxTextEntryDialog, getValue, 0}},
- {2310, {wxTextEntryDialog, setValue, 1}},
- {2311, {wxTextEntryDialog, 'Destroy', undefined}},
- {2312, {wxPasswordEntryDialog, new, 3}},
- {2313, {wxPasswordEntryDialog, 'Destroy', undefined}},
- {2314, {wxFontData, new_0, 0}},
- {2315, {wxFontData, new_1, 1}},
- {2316, {wxFontData, destruct, 0}},
- {2317, {wxFontData, enableEffects, 1}},
- {2318, {wxFontData, getAllowSymbols, 0}},
- {2319, {wxFontData, getColour, 0}},
- {2320, {wxFontData, getChosenFont, 0}},
- {2321, {wxFontData, getEnableEffects, 0}},
- {2322, {wxFontData, getInitialFont, 0}},
- {2323, {wxFontData, getShowHelp, 0}},
- {2324, {wxFontData, setAllowSymbols, 1}},
- {2325, {wxFontData, setChosenFont, 1}},
- {2326, {wxFontData, setColour, 1}},
- {2327, {wxFontData, setInitialFont, 1}},
- {2328, {wxFontData, setRange, 2}},
- {2329, {wxFontData, setShowHelp, 1}},
- {2333, {wxFontDialog, new_0, 0}},
- {2335, {wxFontDialog, new_2, 2}},
- {2337, {wxFontDialog, create, 2}},
- {2338, {wxFontDialog, getFontData, 0}},
- {2340, {wxFontDialog, 'Destroy', undefined}},
- {2341, {wxProgressDialog, new, 3}},
- {2342, {wxProgressDialog, destruct, 0}},
- {2343, {wxProgressDialog, resume, 0}},
- {2344, {wxProgressDialog, update_2, 2}},
- {2345, {wxProgressDialog, update_0, 0}},
- {2346, {wxMessageDialog, new, 3}},
- {2347, {wxMessageDialog, destruct, 0}},
- {2348, {wxPageSetupDialog, new, 2}},
- {2349, {wxPageSetupDialog, destruct, 0}},
- {2350, {wxPageSetupDialog, getPageSetupData, 0}},
- {2351, {wxPageSetupDialog, showModal, 0}},
- {2352, {wxPageSetupDialogData, new_0, 0}},
- {2353, {wxPageSetupDialogData, new_1_0, 1}},
- {2354, {wxPageSetupDialogData, new_1_1, 1}},
- {2355, {wxPageSetupDialogData, destruct, 0}},
- {2356, {wxPageSetupDialogData, enableHelp, 1}},
- {2357, {wxPageSetupDialogData, enableMargins, 1}},
- {2358, {wxPageSetupDialogData, enableOrientation, 1}},
- {2359, {wxPageSetupDialogData, enablePaper, 1}},
- {2360, {wxPageSetupDialogData, enablePrinter, 1}},
- {2361, {wxPageSetupDialogData, getDefaultMinMargins, 0}},
- {2362, {wxPageSetupDialogData, getEnableMargins, 0}},
- {2363, {wxPageSetupDialogData, getEnableOrientation, 0}},
- {2364, {wxPageSetupDialogData, getEnablePaper, 0}},
- {2365, {wxPageSetupDialogData, getEnablePrinter, 0}},
- {2366, {wxPageSetupDialogData, getEnableHelp, 0}},
- {2367, {wxPageSetupDialogData, getDefaultInfo, 0}},
- {2368, {wxPageSetupDialogData, getMarginTopLeft, 0}},
- {2369, {wxPageSetupDialogData, getMarginBottomRight, 0}},
- {2370, {wxPageSetupDialogData, getMinMarginTopLeft, 0}},
- {2371, {wxPageSetupDialogData, getMinMarginBottomRight, 0}},
- {2372, {wxPageSetupDialogData, getPaperId, 0}},
- {2373, {wxPageSetupDialogData, getPaperSize, 0}},
- {2375, {wxPageSetupDialogData, getPrintData, 0}},
- {2376, {wxPageSetupDialogData, isOk, 0}},
- {2377, {wxPageSetupDialogData, setDefaultInfo, 1}},
- {2378, {wxPageSetupDialogData, setDefaultMinMargins, 1}},
- {2379, {wxPageSetupDialogData, setMarginTopLeft, 1}},
- {2380, {wxPageSetupDialogData, setMarginBottomRight, 1}},
- {2381, {wxPageSetupDialogData, setMinMarginTopLeft, 1}},
- {2382, {wxPageSetupDialogData, setMinMarginBottomRight, 1}},
- {2383, {wxPageSetupDialogData, setPaperId, 1}},
- {2384, {wxPageSetupDialogData, setPaperSize_1_1, 1}},
- {2385, {wxPageSetupDialogData, setPaperSize_1_0, 1}},
- {2386, {wxPageSetupDialogData, setPrintData, 1}},
- {2387, {wxPrintDialog, new_2_0, 2}},
- {2388, {wxPrintDialog, new_2_1, 2}},
- {2389, {wxPrintDialog, destruct, 0}},
- {2390, {wxPrintDialog, getPrintDialogData, 0}},
- {2391, {wxPrintDialog, getPrintDC, 0}},
- {2392, {wxPrintDialogData, new_0, 0}},
- {2393, {wxPrintDialogData, new_1_1, 1}},
- {2394, {wxPrintDialogData, new_1_0, 1}},
- {2395, {wxPrintDialogData, destruct, 0}},
- {2396, {wxPrintDialogData, enableHelp, 1}},
- {2397, {wxPrintDialogData, enablePageNumbers, 1}},
- {2398, {wxPrintDialogData, enablePrintToFile, 1}},
- {2399, {wxPrintDialogData, enableSelection, 1}},
- {2400, {wxPrintDialogData, getAllPages, 0}},
- {2401, {wxPrintDialogData, getCollate, 0}},
- {2402, {wxPrintDialogData, getFromPage, 0}},
- {2403, {wxPrintDialogData, getMaxPage, 0}},
- {2404, {wxPrintDialogData, getMinPage, 0}},
- {2405, {wxPrintDialogData, getNoCopies, 0}},
- {2406, {wxPrintDialogData, getPrintData, 0}},
- {2407, {wxPrintDialogData, getPrintToFile, 0}},
- {2408, {wxPrintDialogData, getSelection, 0}},
- {2409, {wxPrintDialogData, getToPage, 0}},
- {2410, {wxPrintDialogData, isOk, 0}},
- {2411, {wxPrintDialogData, setCollate, 1}},
- {2412, {wxPrintDialogData, setFromPage, 1}},
- {2413, {wxPrintDialogData, setMaxPage, 1}},
- {2414, {wxPrintDialogData, setMinPage, 1}},
- {2415, {wxPrintDialogData, setNoCopies, 1}},
- {2416, {wxPrintDialogData, setPrintData, 1}},
- {2417, {wxPrintDialogData, setPrintToFile, 1}},
- {2418, {wxPrintDialogData, setSelection, 1}},
- {2419, {wxPrintDialogData, setToPage, 1}},
- {2420, {wxPrintData, new_0, 0}},
- {2421, {wxPrintData, new_1, 1}},
- {2422, {wxPrintData, destruct, 0}},
- {2423, {wxPrintData, getCollate, 0}},
- {2424, {wxPrintData, getBin, 0}},
- {2425, {wxPrintData, getColour, 0}},
- {2426, {wxPrintData, getDuplex, 0}},
- {2427, {wxPrintData, getNoCopies, 0}},
- {2428, {wxPrintData, getOrientation, 0}},
- {2429, {wxPrintData, getPaperId, 0}},
- {2430, {wxPrintData, getPrinterName, 0}},
- {2431, {wxPrintData, getQuality, 0}},
- {2432, {wxPrintData, isOk, 0}},
- {2433, {wxPrintData, setBin, 1}},
- {2434, {wxPrintData, setCollate, 1}},
- {2435, {wxPrintData, setColour, 1}},
- {2436, {wxPrintData, setDuplex, 1}},
- {2437, {wxPrintData, setNoCopies, 1}},
- {2438, {wxPrintData, setOrientation, 1}},
- {2439, {wxPrintData, setPaperId, 1}},
- {2440, {wxPrintData, setPrinterName, 1}},
- {2441, {wxPrintData, setQuality, 1}},
- {2444, {wxPrintPreview, new_2, 2}},
- {2445, {wxPrintPreview, new_3, 3}},
- {2447, {wxPrintPreview, destruct, 0}},
- {2448, {wxPrintPreview, getCanvas, 0}},
- {2449, {wxPrintPreview, getCurrentPage, 0}},
- {2450, {wxPrintPreview, getFrame, 0}},
- {2451, {wxPrintPreview, getMaxPage, 0}},
- {2452, {wxPrintPreview, getMinPage, 0}},
- {2453, {wxPrintPreview, getPrintout, 0}},
- {2454, {wxPrintPreview, getPrintoutForPrinting, 0}},
- {2455, {wxPrintPreview, isOk, 0}},
- {2456, {wxPrintPreview, paintPage, 2}},
- {2457, {wxPrintPreview, print, 1}},
- {2458, {wxPrintPreview, renderPage, 1}},
- {2459, {wxPrintPreview, setCanvas, 1}},
- {2460, {wxPrintPreview, setCurrentPage, 1}},
- {2461, {wxPrintPreview, setFrame, 1}},
- {2462, {wxPrintPreview, setPrintout, 1}},
- {2463, {wxPrintPreview, setZoom, 1}},
- {2464, {wxPreviewFrame, new, 3}},
- {2465, {wxPreviewFrame, destruct, 0}},
- {2466, {wxPreviewFrame, createControlBar, 0}},
- {2467, {wxPreviewFrame, createCanvas, 0}},
- {2468, {wxPreviewFrame, initialize, 0}},
- {2469, {wxPreviewFrame, onCloseWindow, 1}},
- {2470, {wxPreviewControlBar, new, 4}},
- {2471, {wxPreviewControlBar, destruct, 0}},
- {2472, {wxPreviewControlBar, createButtons, 0}},
- {2473, {wxPreviewControlBar, getPrintPreview, 0}},
- {2474, {wxPreviewControlBar, getZoomControl, 0}},
- {2475, {wxPreviewControlBar, setZoomControl, 1}},
- {2477, {wxPrinter, new, 1}},
- {2478, {wxPrinter, createAbortWindow, 2}},
- {2479, {wxPrinter, getAbort, 0}},
- {2480, {wxPrinter, getLastError, 0}},
- {2481, {wxPrinter, getPrintDialogData, 0}},
- {2482, {wxPrinter, print, 3}},
- {2483, {wxPrinter, printDialog, 1}},
- {2484, {wxPrinter, reportError, 3}},
- {2485, {wxPrinter, setup, 1}},
- {2486, {wxPrinter, 'Destroy', undefined}},
- {2487, {wxXmlResource, new_1, 1}},
- {2488, {wxXmlResource, new_2, 2}},
- {2489, {wxXmlResource, destruct, 0}},
- {2490, {wxXmlResource, attachUnknownControl, 3}},
- {2491, {wxXmlResource, clearHandlers, 0}},
- {2492, {wxXmlResource, compareVersion, 4}},
- {2493, {wxXmlResource, get, 0}},
- {2494, {wxXmlResource, getFlags, 0}},
- {2495, {wxXmlResource, getVersion, 0}},
- {2496, {wxXmlResource, getXRCID, 2}},
- {2497, {wxXmlResource, initAllHandlers, 0}},
- {2498, {wxXmlResource, load, 1}},
- {2499, {wxXmlResource, loadBitmap, 1}},
- {2500, {wxXmlResource, loadDialog_2, 2}},
- {2501, {wxXmlResource, loadDialog_3, 3}},
- {2502, {wxXmlResource, loadFrame_2, 2}},
- {2503, {wxXmlResource, loadFrame_3, 3}},
- {2504, {wxXmlResource, loadIcon, 1}},
- {2505, {wxXmlResource, loadMenu, 1}},
- {2506, {wxXmlResource, loadMenuBar_2, 2}},
- {2507, {wxXmlResource, loadMenuBar_1, 1}},
- {2508, {wxXmlResource, loadPanel_2, 2}},
- {2509, {wxXmlResource, loadPanel_3, 3}},
- {2510, {wxXmlResource, loadToolBar, 2}},
- {2511, {wxXmlResource, set, 1}},
- {2512, {wxXmlResource, setFlags, 1}},
- {2513, {wxXmlResource, unload, 1}},
- {2514, {wxXmlResource, xrcctrl, 3}},
- {2515, {wxHtmlEasyPrinting, new, 1}},
- {2516, {wxHtmlEasyPrinting, destruct, 0}},
- {2517, {wxHtmlEasyPrinting, getPrintData, 0}},
- {2518, {wxHtmlEasyPrinting, getPageSetupData, 0}},
- {2519, {wxHtmlEasyPrinting, previewFile, 1}},
- {2520, {wxHtmlEasyPrinting, previewText, 2}},
- {2521, {wxHtmlEasyPrinting, printFile, 1}},
- {2522, {wxHtmlEasyPrinting, printText, 2}},
- {2523, {wxHtmlEasyPrinting, pageSetup, 0}},
- {2524, {wxHtmlEasyPrinting, setFonts, 3}},
- {2525, {wxHtmlEasyPrinting, setHeader, 2}},
- {2526, {wxHtmlEasyPrinting, setFooter, 2}},
- {2528, {wxGLCanvas, new_2, 2}},
- {2529, {wxGLCanvas, new_3_1, 3}},
- {2530, {wxGLCanvas, new_3_0, 3}},
- {2531, {wxGLCanvas, getContext, 0}},
- {2533, {wxGLCanvas, setCurrent, 0}},
- {2534, {wxGLCanvas, swapBuffers, 0}},
- {2535, {wxGLCanvas, 'Destroy', undefined}},
- {2536, {wxAuiManager, new, 1}},
- {2537, {wxAuiManager, destruct, 0}},
- {2538, {wxAuiManager, addPane_2_1, 2}},
- {2539, {wxAuiManager, addPane_3, 3}},
- {2540, {wxAuiManager, addPane_2_0, 2}},
- {2541, {wxAuiManager, detachPane, 1}},
- {2542, {wxAuiManager, getAllPanes, 0}},
- {2543, {wxAuiManager, getArtProvider, 0}},
- {2544, {wxAuiManager, getDockSizeConstraint, 2}},
- {2545, {wxAuiManager, getFlags, 0}},
- {2546, {wxAuiManager, getManagedWindow, 0}},
- {2547, {wxAuiManager, getManager, 1}},
- {2548, {wxAuiManager, getPane_1_1, 1}},
- {2549, {wxAuiManager, getPane_1_0, 1}},
- {2550, {wxAuiManager, hideHint, 0}},
- {2551, {wxAuiManager, insertPane, 3}},
- {2552, {wxAuiManager, loadPaneInfo, 2}},
- {2553, {wxAuiManager, loadPerspective, 2}},
- {2554, {wxAuiManager, savePaneInfo, 1}},
- {2555, {wxAuiManager, savePerspective, 0}},
- {2556, {wxAuiManager, setArtProvider, 1}},
- {2557, {wxAuiManager, setDockSizeConstraint, 2}},
- {2558, {wxAuiManager, setFlags, 1}},
- {2559, {wxAuiManager, setManagedWindow, 1}},
- {2560, {wxAuiManager, showHint, 1}},
- {2561, {wxAuiManager, unInit, 0}},
- {2562, {wxAuiManager, update, 0}},
- {2563, {wxAuiPaneInfo, new_0, 0}},
- {2564, {wxAuiPaneInfo, new_1, 1}},
- {2565, {wxAuiPaneInfo, destruct, 0}},
- {2566, {wxAuiPaneInfo, bestSize_1, 1}},
- {2567, {wxAuiPaneInfo, bestSize_2, 2}},
- {2568, {wxAuiPaneInfo, bottom, 0}},
- {2569, {wxAuiPaneInfo, bottomDockable, 1}},
- {2570, {wxAuiPaneInfo, caption, 1}},
- {2571, {wxAuiPaneInfo, captionVisible, 1}},
- {2572, {wxAuiPaneInfo, centre, 0}},
- {2573, {wxAuiPaneInfo, centrePane, 0}},
- {2574, {wxAuiPaneInfo, closeButton, 1}},
- {2575, {wxAuiPaneInfo, defaultPane, 0}},
- {2576, {wxAuiPaneInfo, destroyOnClose, 1}},
- {2577, {wxAuiPaneInfo, direction, 1}},
- {2578, {wxAuiPaneInfo, dock, 0}},
- {2579, {wxAuiPaneInfo, dockable, 1}},
- {2580, {wxAuiPaneInfo, fixed, 0}},
- {2581, {wxAuiPaneInfo, float, 0}},
- {2582, {wxAuiPaneInfo, floatable, 1}},
- {2583, {wxAuiPaneInfo, floatingPosition_1, 1}},
- {2584, {wxAuiPaneInfo, floatingPosition_2, 2}},
- {2585, {wxAuiPaneInfo, floatingSize_1, 1}},
- {2586, {wxAuiPaneInfo, floatingSize_2, 2}},
- {2587, {wxAuiPaneInfo, gripper, 1}},
- {2588, {wxAuiPaneInfo, gripperTop, 1}},
- {2589, {wxAuiPaneInfo, hasBorder, 0}},
- {2590, {wxAuiPaneInfo, hasCaption, 0}},
- {2591, {wxAuiPaneInfo, hasCloseButton, 0}},
- {2592, {wxAuiPaneInfo, hasFlag, 1}},
- {2593, {wxAuiPaneInfo, hasGripper, 0}},
- {2594, {wxAuiPaneInfo, hasGripperTop, 0}},
- {2595, {wxAuiPaneInfo, hasMaximizeButton, 0}},
- {2596, {wxAuiPaneInfo, hasMinimizeButton, 0}},
- {2597, {wxAuiPaneInfo, hasPinButton, 0}},
- {2598, {wxAuiPaneInfo, hide, 0}},
- {2599, {wxAuiPaneInfo, isBottomDockable, 0}},
- {2600, {wxAuiPaneInfo, isDocked, 0}},
- {2601, {wxAuiPaneInfo, isFixed, 0}},
- {2602, {wxAuiPaneInfo, isFloatable, 0}},
- {2603, {wxAuiPaneInfo, isFloating, 0}},
- {2604, {wxAuiPaneInfo, isLeftDockable, 0}},
- {2605, {wxAuiPaneInfo, isMovable, 0}},
- {2606, {wxAuiPaneInfo, isOk, 0}},
- {2607, {wxAuiPaneInfo, isResizable, 0}},
- {2608, {wxAuiPaneInfo, isRightDockable, 0}},
- {2609, {wxAuiPaneInfo, isShown, 0}},
- {2610, {wxAuiPaneInfo, isToolbar, 0}},
- {2611, {wxAuiPaneInfo, isTopDockable, 0}},
- {2612, {wxAuiPaneInfo, layer, 1}},
- {2613, {wxAuiPaneInfo, left, 0}},
- {2614, {wxAuiPaneInfo, leftDockable, 1}},
- {2615, {wxAuiPaneInfo, maxSize_1, 1}},
- {2616, {wxAuiPaneInfo, maxSize_2, 2}},
- {2617, {wxAuiPaneInfo, maximizeButton, 1}},
- {2618, {wxAuiPaneInfo, minSize_1, 1}},
- {2619, {wxAuiPaneInfo, minSize_2, 2}},
- {2620, {wxAuiPaneInfo, minimizeButton, 1}},
- {2621, {wxAuiPaneInfo, movable, 1}},
- {2622, {wxAuiPaneInfo, name, 1}},
- {2623, {wxAuiPaneInfo, paneBorder, 1}},
- {2624, {wxAuiPaneInfo, pinButton, 1}},
- {2625, {wxAuiPaneInfo, position, 1}},
- {2626, {wxAuiPaneInfo, resizable, 1}},
- {2627, {wxAuiPaneInfo, right, 0}},
- {2628, {wxAuiPaneInfo, rightDockable, 1}},
- {2629, {wxAuiPaneInfo, row, 1}},
- {2630, {wxAuiPaneInfo, safeSet, 1}},
- {2631, {wxAuiPaneInfo, setFlag, 2}},
- {2632, {wxAuiPaneInfo, show, 1}},
- {2633, {wxAuiPaneInfo, toolbarPane, 0}},
- {2634, {wxAuiPaneInfo, top, 0}},
- {2635, {wxAuiPaneInfo, topDockable, 1}},
- {2636, {wxAuiPaneInfo, window, 1}},
- {2637, {wxAuiNotebook, new_0, 0}},
- {2638, {wxAuiNotebook, new_2, 2}},
- {2639, {wxAuiNotebook, addPage, 3}},
- {2640, {wxAuiNotebook, create, 2}},
- {2641, {wxAuiNotebook, deletePage, 1}},
- {2642, {wxAuiNotebook, getArtProvider, 0}},
- {2643, {wxAuiNotebook, getPage, 1}},
- {2644, {wxAuiNotebook, getPageBitmap, 1}},
- {2645, {wxAuiNotebook, getPageCount, 0}},
- {2646, {wxAuiNotebook, getPageIndex, 1}},
- {2647, {wxAuiNotebook, getPageText, 1}},
- {2648, {wxAuiNotebook, getSelection, 0}},
- {2649, {wxAuiNotebook, insertPage, 4}},
- {2650, {wxAuiNotebook, removePage, 1}},
- {2651, {wxAuiNotebook, setArtProvider, 1}},
- {2652, {wxAuiNotebook, setFont, 1}},
- {2653, {wxAuiNotebook, setPageBitmap, 2}},
- {2654, {wxAuiNotebook, setPageText, 2}},
- {2655, {wxAuiNotebook, setSelection, 1}},
- {2656, {wxAuiNotebook, setTabCtrlHeight, 1}},
- {2657, {wxAuiNotebook, setUniformBitmapSize, 1}},
- {2658, {wxAuiNotebook, 'Destroy', undefined}},
- {2659, {wxMDIParentFrame, new_0, 0}},
- {2660, {wxMDIParentFrame, new_4, 4}},
- {2661, {wxMDIParentFrame, destruct, 0}},
- {2662, {wxMDIParentFrame, activateNext, 0}},
- {2663, {wxMDIParentFrame, activatePrevious, 0}},
- {2664, {wxMDIParentFrame, arrangeIcons, 0}},
- {2665, {wxMDIParentFrame, cascade, 0}},
- {2666, {wxMDIParentFrame, create, 4}},
- {2667, {wxMDIParentFrame, getActiveChild, 0}},
- {2668, {wxMDIParentFrame, getClientWindow, 0}},
- {2669, {wxMDIParentFrame, tile, 1}},
- {2670, {wxMDIChildFrame, new_0, 0}},
- {2671, {wxMDIChildFrame, new_4, 4}},
- {2672, {wxMDIChildFrame, destruct, 0}},
- {2673, {wxMDIChildFrame, activate, 0}},
- {2674, {wxMDIChildFrame, create, 4}},
- {2675, {wxMDIChildFrame, maximize, 1}},
- {2676, {wxMDIChildFrame, restore, 0}},
- {2677, {wxMDIClientWindow, new_0, 0}},
- {2678, {wxMDIClientWindow, new_2, 2}},
- {2679, {wxMDIClientWindow, destruct, 0}},
- {2680, {wxMDIClientWindow, createClient, 2}},
- {2681, {wxLayoutAlgorithm, new, 0}},
- {2682, {wxLayoutAlgorithm, layoutFrame, 2}},
- {2683, {wxLayoutAlgorithm, layoutMDIFrame, 2}},
- {2684, {wxLayoutAlgorithm, layoutWindow, 2}},
- {2685, {wxLayoutAlgorithm, 'Destroy', undefined}},
- {2686, {wxEvent, getId, 0}},
- {2687, {wxEvent, getSkipped, 0}},
- {2688, {wxEvent, getTimestamp, 0}},
- {2689, {wxEvent, isCommandEvent, 0}},
- {2690, {wxEvent, resumePropagation, 1}},
- {2691, {wxEvent, shouldPropagate, 0}},
- {2692, {wxEvent, skip, 1}},
- {2693, {wxEvent, stopPropagation, 0}},
- {2694, {wxCommandEvent, getClientData, 0}},
- {2695, {wxCommandEvent, getExtraLong, 0}},
- {2696, {wxCommandEvent, getInt, 0}},
- {2697, {wxCommandEvent, getSelection, 0}},
- {2698, {wxCommandEvent, getString, 0}},
- {2699, {wxCommandEvent, isChecked, 0}},
- {2700, {wxCommandEvent, isSelection, 0}},
- {2701, {wxCommandEvent, setInt, 1}},
- {2702, {wxCommandEvent, setString, 1}},
- {2703, {wxScrollEvent, getOrientation, 0}},
- {2704, {wxScrollEvent, getPosition, 0}},
- {2705, {wxScrollWinEvent, getOrientation, 0}},
- {2706, {wxScrollWinEvent, getPosition, 0}},
- {2707, {wxMouseEvent, altDown, 0}},
- {2708, {wxMouseEvent, button, 1}},
- {2709, {wxMouseEvent, buttonDClick, 1}},
- {2710, {wxMouseEvent, buttonDown, 1}},
- {2711, {wxMouseEvent, buttonUp, 1}},
- {2712, {wxMouseEvent, cmdDown, 0}},
- {2713, {wxMouseEvent, controlDown, 0}},
- {2714, {wxMouseEvent, dragging, 0}},
- {2715, {wxMouseEvent, entering, 0}},
- {2716, {wxMouseEvent, getButton, 0}},
- {2719, {wxMouseEvent, getPosition, 0}},
- {2720, {wxMouseEvent, getLogicalPosition, 1}},
- {2721, {wxMouseEvent, getLinesPerAction, 0}},
- {2722, {wxMouseEvent, getWheelRotation, 0}},
- {2723, {wxMouseEvent, getWheelDelta, 0}},
- {2724, {wxMouseEvent, getX, 0}},
- {2725, {wxMouseEvent, getY, 0}},
- {2726, {wxMouseEvent, isButton, 0}},
- {2727, {wxMouseEvent, isPageScroll, 0}},
- {2728, {wxMouseEvent, leaving, 0}},
- {2729, {wxMouseEvent, leftDClick, 0}},
- {2730, {wxMouseEvent, leftDown, 0}},
- {2731, {wxMouseEvent, leftIsDown, 0}},
- {2732, {wxMouseEvent, leftUp, 0}},
- {2733, {wxMouseEvent, metaDown, 0}},
- {2734, {wxMouseEvent, middleDClick, 0}},
- {2735, {wxMouseEvent, middleDown, 0}},
- {2736, {wxMouseEvent, middleIsDown, 0}},
- {2737, {wxMouseEvent, middleUp, 0}},
- {2738, {wxMouseEvent, moving, 0}},
- {2739, {wxMouseEvent, rightDClick, 0}},
- {2740, {wxMouseEvent, rightDown, 0}},
- {2741, {wxMouseEvent, rightIsDown, 0}},
- {2742, {wxMouseEvent, rightUp, 0}},
- {2743, {wxMouseEvent, shiftDown, 0}},
- {2744, {wxSetCursorEvent, getCursor, 0}},
- {2745, {wxSetCursorEvent, getX, 0}},
- {2746, {wxSetCursorEvent, getY, 0}},
- {2747, {wxSetCursorEvent, hasCursor, 0}},
- {2748, {wxSetCursorEvent, setCursor, 1}},
- {2749, {wxKeyEvent, altDown, 0}},
- {2750, {wxKeyEvent, cmdDown, 0}},
- {2751, {wxKeyEvent, controlDown, 0}},
- {2752, {wxKeyEvent, getKeyCode, 0}},
- {2753, {wxKeyEvent, getModifiers, 0}},
- {2756, {wxKeyEvent, getPosition, 0}},
- {2757, {wxKeyEvent, getRawKeyCode, 0}},
- {2758, {wxKeyEvent, getRawKeyFlags, 0}},
- {2759, {wxKeyEvent, getUnicodeKey, 0}},
- {2760, {wxKeyEvent, getX, 0}},
- {2761, {wxKeyEvent, getY, 0}},
- {2762, {wxKeyEvent, hasModifiers, 0}},
- {2763, {wxKeyEvent, metaDown, 0}},
- {2764, {wxKeyEvent, shiftDown, 0}},
- {2765, {wxSizeEvent, getSize, 0}},
- {2766, {wxMoveEvent, getPosition, 0}},
- {2767, {wxEraseEvent, getDC, 0}},
- {2768, {wxFocusEvent, getWindow, 0}},
- {2769, {wxChildFocusEvent, getWindow, 0}},
- {2770, {wxMenuEvent, getMenu, 0}},
- {2771, {wxMenuEvent, getMenuId, 0}},
- {2772, {wxMenuEvent, isPopup, 0}},
- {2773, {wxCloseEvent, canVeto, 0}},
- {2774, {wxCloseEvent, getLoggingOff, 0}},
- {2775, {wxCloseEvent, setCanVeto, 1}},
- {2776, {wxCloseEvent, setLoggingOff, 1}},
- {2777, {wxCloseEvent, veto, 1}},
- {2778, {wxShowEvent, setShow, 1}},
- {2779, {wxShowEvent, getShow, 0}},
- {2780, {wxIconizeEvent, iconized, 0}},
- {2781, {wxJoystickEvent, buttonDown, 1}},
- {2782, {wxJoystickEvent, buttonIsDown, 1}},
- {2783, {wxJoystickEvent, buttonUp, 1}},
- {2784, {wxJoystickEvent, getButtonChange, 0}},
- {2785, {wxJoystickEvent, getButtonState, 0}},
- {2786, {wxJoystickEvent, getJoystick, 0}},
- {2787, {wxJoystickEvent, getPosition, 0}},
- {2788, {wxJoystickEvent, getZPosition, 0}},
- {2789, {wxJoystickEvent, isButton, 0}},
- {2790, {wxJoystickEvent, isMove, 0}},
- {2791, {wxJoystickEvent, isZMove, 0}},
- {2792, {wxUpdateUIEvent, canUpdate, 1}},
- {2793, {wxUpdateUIEvent, check, 1}},
- {2794, {wxUpdateUIEvent, enable, 1}},
- {2795, {wxUpdateUIEvent, show, 1}},
- {2796, {wxUpdateUIEvent, getChecked, 0}},
- {2797, {wxUpdateUIEvent, getEnabled, 0}},
- {2798, {wxUpdateUIEvent, getShown, 0}},
- {2799, {wxUpdateUIEvent, getSetChecked, 0}},
- {2800, {wxUpdateUIEvent, getSetEnabled, 0}},
- {2801, {wxUpdateUIEvent, getSetShown, 0}},
- {2802, {wxUpdateUIEvent, getSetText, 0}},
- {2803, {wxUpdateUIEvent, getText, 0}},
- {2804, {wxUpdateUIEvent, getMode, 0}},
- {2805, {wxUpdateUIEvent, getUpdateInterval, 0}},
- {2806, {wxUpdateUIEvent, resetUpdateTime, 0}},
- {2807, {wxUpdateUIEvent, setMode, 1}},
- {2808, {wxUpdateUIEvent, setText, 1}},
- {2809, {wxUpdateUIEvent, setUpdateInterval, 1}},
- {2810, {wxMouseCaptureChangedEvent, getCapturedWindow, 0}},
- {2811, {wxPaletteChangedEvent, setChangedWindow, 1}},
- {2812, {wxPaletteChangedEvent, getChangedWindow, 0}},
- {2813, {wxQueryNewPaletteEvent, setPaletteRealized, 1}},
- {2814, {wxQueryNewPaletteEvent, getPaletteRealized, 0}},
- {2815, {wxNavigationKeyEvent, getDirection, 0}},
- {2816, {wxNavigationKeyEvent, setDirection, 1}},
- {2817, {wxNavigationKeyEvent, isWindowChange, 0}},
- {2818, {wxNavigationKeyEvent, setWindowChange, 1}},
- {2819, {wxNavigationKeyEvent, isFromTab, 0}},
- {2820, {wxNavigationKeyEvent, setFromTab, 1}},
- {2821, {wxNavigationKeyEvent, getCurrentFocus, 0}},
- {2822, {wxNavigationKeyEvent, setCurrentFocus, 1}},
- {2823, {wxHelpEvent, getOrigin, 0}},
- {2824, {wxHelpEvent, getPosition, 0}},
- {2825, {wxHelpEvent, setOrigin, 1}},
- {2826, {wxHelpEvent, setPosition, 1}},
- {2827, {wxContextMenuEvent, getPosition, 0}},
- {2828, {wxContextMenuEvent, setPosition, 1}},
- {2829, {wxIdleEvent, canSend, 1}},
- {2830, {wxIdleEvent, getMode, 0}},
- {2831, {wxIdleEvent, requestMore, 1}},
- {2832, {wxIdleEvent, moreRequested, 0}},
- {2833, {wxIdleEvent, setMode, 1}},
- {2834, {wxGridEvent, altDown, 0}},
- {2835, {wxGridEvent, controlDown, 0}},
- {2836, {wxGridEvent, getCol, 0}},
- {2837, {wxGridEvent, getPosition, 0}},
- {2838, {wxGridEvent, getRow, 0}},
- {2839, {wxGridEvent, metaDown, 0}},
- {2840, {wxGridEvent, selecting, 0}},
- {2841, {wxGridEvent, shiftDown, 0}},
- {2842, {wxNotifyEvent, allow, 0}},
- {2843, {wxNotifyEvent, isAllowed, 0}},
- {2844, {wxNotifyEvent, veto, 0}},
- {2845, {wxSashEvent, getEdge, 0}},
- {2846, {wxSashEvent, getDragRect, 0}},
- {2847, {wxSashEvent, getDragStatus, 0}},
- {2848, {wxListEvent, getCacheFrom, 0}},
- {2849, {wxListEvent, getCacheTo, 0}},
- {2850, {wxListEvent, getKeyCode, 0}},
- {2851, {wxListEvent, getIndex, 0}},
- {2852, {wxListEvent, getColumn, 0}},
- {2853, {wxListEvent, getPoint, 0}},
- {2854, {wxListEvent, getLabel, 0}},
- {2855, {wxListEvent, getText, 0}},
- {2856, {wxListEvent, getImage, 0}},
- {2857, {wxListEvent, getData, 0}},
- {2858, {wxListEvent, getMask, 0}},
- {2859, {wxListEvent, getItem, 0}},
- {2860, {wxListEvent, isEditCancelled, 0}},
- {2861, {wxDateEvent, getDate, 0}},
- {2862, {wxCalendarEvent, getWeekDay, 0}},
- {2863, {wxFileDirPickerEvent, getPath, 0}},
- {2864, {wxColourPickerEvent, getColour, 0}},
- {2865, {wxFontPickerEvent, getFont, 0}},
- {2866, {wxStyledTextEvent, getPosition, 0}},
- {2867, {wxStyledTextEvent, getKey, 0}},
- {2868, {wxStyledTextEvent, getModifiers, 0}},
- {2869, {wxStyledTextEvent, getModificationType, 0}},
- {2870, {wxStyledTextEvent, getText, 0}},
- {2871, {wxStyledTextEvent, getLength, 0}},
- {2872, {wxStyledTextEvent, getLinesAdded, 0}},
- {2873, {wxStyledTextEvent, getLine, 0}},
- {2874, {wxStyledTextEvent, getFoldLevelNow, 0}},
- {2875, {wxStyledTextEvent, getFoldLevelPrev, 0}},
- {2876, {wxStyledTextEvent, getMargin, 0}},
- {2877, {wxStyledTextEvent, getMessage, 0}},
- {2878, {wxStyledTextEvent, getWParam, 0}},
- {2879, {wxStyledTextEvent, getLParam, 0}},
- {2880, {wxStyledTextEvent, getListType, 0}},
- {2881, {wxStyledTextEvent, getX, 0}},
- {2882, {wxStyledTextEvent, getY, 0}},
- {2883, {wxStyledTextEvent, getDragText, 0}},
- {2884, {wxStyledTextEvent, getDragAllowMove, 0}},
- {2885, {wxStyledTextEvent, getDragResult, 0}},
- {2886, {wxStyledTextEvent, getShift, 0}},
- {2887, {wxStyledTextEvent, getControl, 0}},
- {2888, {wxStyledTextEvent, getAlt, 0}},
- {2889, {utils, getKeyState, 1}},
- {2890, {utils, getMousePosition, 2}},
- {2891, {utils, getMouseState, 0}},
- {2892, {utils, setDetectableAutoRepeat, 1}},
- {2893, {utils, bell, 0}},
- {2894, {utils, findMenuItemId, 3}},
- {2895, {utils, genericFindWindowAtPoint, 1}},
- {2896, {utils, findWindowAtPoint, 1}},
- {2897, {utils, beginBusyCursor, 1}},
- {2898, {utils, endBusyCursor, 0}},
- {2899, {utils, isBusy, 0}},
- {2900, {utils, shutdown, 1}},
- {2901, {utils, shell, 1}},
- {2902, {utils, launchDefaultBrowser, 2}},
- {2903, {utils, getEmailAddress, 0}},
- {2904, {utils, getUserId, 0}},
- {2905, {utils, getHomeDir, 0}},
- {2906, {utils, newId, 0}},
- {2907, {utils, registerId, 1}},
- {2908, {utils, getCurrentId, 0}},
- {2909, {utils, getOsDescription, 0}},
- {2910, {utils, isPlatformLittleEndian, 0}},
- {2911, {utils, isPlatform64Bit, 0}},
- {2912, {wxPrintout, new, 1}},
- {2913, {wxPrintout, destruct, 0}},
- {2914, {wxPrintout, getDC, 0}},
- {2915, {wxPrintout, getPageSizeMM, 2}},
- {2916, {wxPrintout, getPageSizePixels, 2}},
- {2917, {wxPrintout, getPaperRectPixels, 0}},
- {2918, {wxPrintout, getPPIPrinter, 2}},
- {2919, {wxPrintout, getPPIScreen, 2}},
- {2920, {wxPrintout, getTitle, 0}},
- {2921, {wxPrintout, isPreview, 0}},
- {2922, {wxPrintout, fitThisSizeToPaper, 1}},
- {2923, {wxPrintout, fitThisSizeToPage, 1}},
- {2924, {wxPrintout, fitThisSizeToPageMargins, 2}},
- {2925, {wxPrintout, mapScreenSizeToPaper, 0}},
- {2926, {wxPrintout, mapScreenSizeToPage, 0}},
- {2927, {wxPrintout, mapScreenSizeToPageMargins, 1}},
- {2928, {wxPrintout, mapScreenSizeToDevice, 0}},
- {2929, {wxPrintout, getLogicalPaperRect, 0}},
- {2930, {wxPrintout, getLogicalPageRect, 0}},
- {2931, {wxPrintout, getLogicalPageMarginsRect, 1}},
- {2932, {wxPrintout, setLogicalOrigin, 2}},
- {2933, {wxPrintout, offsetLogicalOrigin, 2}},
- {2934, {wxStyledTextCtrl, new_2, 2}},
- {2935, {wxStyledTextCtrl, new_0, 0}},
- {2936, {wxStyledTextCtrl, destruct, 0}},
- {2937, {wxStyledTextCtrl, create, 2}},
- {2938, {wxStyledTextCtrl, addText, 1}},
- {2939, {wxStyledTextCtrl, addStyledText, 1}},
- {2940, {wxStyledTextCtrl, insertText, 2}},
- {2941, {wxStyledTextCtrl, clearAll, 0}},
- {2942, {wxStyledTextCtrl, clearDocumentStyle, 0}},
- {2943, {wxStyledTextCtrl, getLength, 0}},
- {2944, {wxStyledTextCtrl, getCharAt, 1}},
- {2945, {wxStyledTextCtrl, getCurrentPos, 0}},
- {2946, {wxStyledTextCtrl, getAnchor, 0}},
- {2947, {wxStyledTextCtrl, getStyleAt, 1}},
- {2948, {wxStyledTextCtrl, redo, 0}},
- {2949, {wxStyledTextCtrl, setUndoCollection, 1}},
- {2950, {wxStyledTextCtrl, selectAll, 0}},
- {2951, {wxStyledTextCtrl, setSavePoint, 0}},
- {2952, {wxStyledTextCtrl, getStyledText, 2}},
- {2953, {wxStyledTextCtrl, canRedo, 0}},
- {2954, {wxStyledTextCtrl, markerLineFromHandle, 1}},
- {2955, {wxStyledTextCtrl, markerDeleteHandle, 1}},
- {2956, {wxStyledTextCtrl, getUndoCollection, 0}},
- {2957, {wxStyledTextCtrl, getViewWhiteSpace, 0}},
- {2958, {wxStyledTextCtrl, setViewWhiteSpace, 1}},
- {2959, {wxStyledTextCtrl, positionFromPoint, 1}},
- {2960, {wxStyledTextCtrl, positionFromPointClose, 2}},
- {2961, {wxStyledTextCtrl, gotoLine, 1}},
- {2962, {wxStyledTextCtrl, gotoPos, 1}},
- {2963, {wxStyledTextCtrl, setAnchor, 1}},
- {2964, {wxStyledTextCtrl, getCurLine, 1}},
- {2965, {wxStyledTextCtrl, getEndStyled, 0}},
- {2966, {wxStyledTextCtrl, convertEOLs, 1}},
- {2967, {wxStyledTextCtrl, getEOLMode, 0}},
- {2968, {wxStyledTextCtrl, setEOLMode, 1}},
- {2969, {wxStyledTextCtrl, startStyling, 2}},
- {2970, {wxStyledTextCtrl, setStyling, 2}},
- {2971, {wxStyledTextCtrl, getBufferedDraw, 0}},
- {2972, {wxStyledTextCtrl, setBufferedDraw, 1}},
- {2973, {wxStyledTextCtrl, setTabWidth, 1}},
- {2974, {wxStyledTextCtrl, getTabWidth, 0}},
- {2975, {wxStyledTextCtrl, setCodePage, 1}},
- {2976, {wxStyledTextCtrl, markerDefine, 3}},
- {2977, {wxStyledTextCtrl, markerSetForeground, 2}},
- {2978, {wxStyledTextCtrl, markerSetBackground, 2}},
- {2979, {wxStyledTextCtrl, markerAdd, 2}},
- {2980, {wxStyledTextCtrl, markerDelete, 2}},
- {2981, {wxStyledTextCtrl, markerDeleteAll, 1}},
- {2982, {wxStyledTextCtrl, markerGet, 1}},
- {2983, {wxStyledTextCtrl, markerNext, 2}},
- {2984, {wxStyledTextCtrl, markerPrevious, 2}},
- {2985, {wxStyledTextCtrl, markerDefineBitmap, 2}},
- {2986, {wxStyledTextCtrl, markerAddSet, 2}},
- {2987, {wxStyledTextCtrl, markerSetAlpha, 2}},
- {2988, {wxStyledTextCtrl, setMarginType, 2}},
- {2989, {wxStyledTextCtrl, getMarginType, 1}},
- {2990, {wxStyledTextCtrl, setMarginWidth, 2}},
- {2991, {wxStyledTextCtrl, getMarginWidth, 1}},
- {2992, {wxStyledTextCtrl, setMarginMask, 2}},
- {2993, {wxStyledTextCtrl, getMarginMask, 1}},
- {2994, {wxStyledTextCtrl, setMarginSensitive, 2}},
- {2995, {wxStyledTextCtrl, getMarginSensitive, 1}},
- {2996, {wxStyledTextCtrl, styleClearAll, 0}},
- {2997, {wxStyledTextCtrl, styleSetForeground, 2}},
- {2998, {wxStyledTextCtrl, styleSetBackground, 2}},
- {2999, {wxStyledTextCtrl, styleSetBold, 2}},
- {3000, {wxStyledTextCtrl, styleSetItalic, 2}},
- {3001, {wxStyledTextCtrl, styleSetSize, 2}},
- {3002, {wxStyledTextCtrl, styleSetFaceName, 2}},
- {3003, {wxStyledTextCtrl, styleSetEOLFilled, 2}},
- {3004, {wxStyledTextCtrl, styleResetDefault, 0}},
- {3005, {wxStyledTextCtrl, styleSetUnderline, 2}},
- {3006, {wxStyledTextCtrl, styleSetCase, 2}},
- {3007, {wxStyledTextCtrl, styleSetHotSpot, 2}},
- {3008, {wxStyledTextCtrl, setSelForeground, 2}},
- {3009, {wxStyledTextCtrl, setSelBackground, 2}},
- {3010, {wxStyledTextCtrl, getSelAlpha, 0}},
- {3011, {wxStyledTextCtrl, setSelAlpha, 1}},
- {3012, {wxStyledTextCtrl, setCaretForeground, 1}},
- {3013, {wxStyledTextCtrl, cmdKeyAssign, 3}},
- {3014, {wxStyledTextCtrl, cmdKeyClear, 2}},
- {3015, {wxStyledTextCtrl, cmdKeyClearAll, 0}},
- {3016, {wxStyledTextCtrl, setStyleBytes, 2}},
- {3017, {wxStyledTextCtrl, styleSetVisible, 2}},
- {3018, {wxStyledTextCtrl, getCaretPeriod, 0}},
- {3019, {wxStyledTextCtrl, setCaretPeriod, 1}},
- {3020, {wxStyledTextCtrl, setWordChars, 1}},
- {3021, {wxStyledTextCtrl, beginUndoAction, 0}},
- {3022, {wxStyledTextCtrl, endUndoAction, 0}},
- {3023, {wxStyledTextCtrl, indicatorSetStyle, 2}},
- {3024, {wxStyledTextCtrl, indicatorGetStyle, 1}},
- {3025, {wxStyledTextCtrl, indicatorSetForeground, 2}},
- {3026, {wxStyledTextCtrl, indicatorGetForeground, 1}},
- {3027, {wxStyledTextCtrl, setWhitespaceForeground, 2}},
- {3028, {wxStyledTextCtrl, setWhitespaceBackground, 2}},
- {3029, {wxStyledTextCtrl, getStyleBits, 0}},
- {3030, {wxStyledTextCtrl, setLineState, 2}},
- {3031, {wxStyledTextCtrl, getLineState, 1}},
- {3032, {wxStyledTextCtrl, getMaxLineState, 0}},
- {3033, {wxStyledTextCtrl, getCaretLineVisible, 0}},
- {3034, {wxStyledTextCtrl, setCaretLineVisible, 1}},
- {3035, {wxStyledTextCtrl, getCaretLineBackground, 0}},
- {3036, {wxStyledTextCtrl, setCaretLineBackground, 1}},
- {3037, {wxStyledTextCtrl, autoCompShow, 2}},
- {3038, {wxStyledTextCtrl, autoCompCancel, 0}},
- {3039, {wxStyledTextCtrl, autoCompActive, 0}},
- {3040, {wxStyledTextCtrl, autoCompPosStart, 0}},
- {3041, {wxStyledTextCtrl, autoCompComplete, 0}},
- {3042, {wxStyledTextCtrl, autoCompStops, 1}},
- {3043, {wxStyledTextCtrl, autoCompSetSeparator, 1}},
- {3044, {wxStyledTextCtrl, autoCompGetSeparator, 0}},
- {3045, {wxStyledTextCtrl, autoCompSelect, 1}},
- {3046, {wxStyledTextCtrl, autoCompSetCancelAtStart, 1}},
- {3047, {wxStyledTextCtrl, autoCompGetCancelAtStart, 0}},
- {3048, {wxStyledTextCtrl, autoCompSetFillUps, 1}},
- {3049, {wxStyledTextCtrl, autoCompSetChooseSingle, 1}},
- {3050, {wxStyledTextCtrl, autoCompGetChooseSingle, 0}},
- {3051, {wxStyledTextCtrl, autoCompSetIgnoreCase, 1}},
- {3052, {wxStyledTextCtrl, autoCompGetIgnoreCase, 0}},
- {3053, {wxStyledTextCtrl, userListShow, 2}},
- {3054, {wxStyledTextCtrl, autoCompSetAutoHide, 1}},
- {3055, {wxStyledTextCtrl, autoCompGetAutoHide, 0}},
- {3056, {wxStyledTextCtrl, autoCompSetDropRestOfWord, 1}},
- {3057, {wxStyledTextCtrl, autoCompGetDropRestOfWord, 0}},
- {3058, {wxStyledTextCtrl, registerImage, 2}},
- {3059, {wxStyledTextCtrl, clearRegisteredImages, 0}},
- {3060, {wxStyledTextCtrl, autoCompGetTypeSeparator, 0}},
- {3061, {wxStyledTextCtrl, autoCompSetTypeSeparator, 1}},
- {3062, {wxStyledTextCtrl, autoCompSetMaxWidth, 1}},
- {3063, {wxStyledTextCtrl, autoCompGetMaxWidth, 0}},
- {3064, {wxStyledTextCtrl, autoCompSetMaxHeight, 1}},
- {3065, {wxStyledTextCtrl, autoCompGetMaxHeight, 0}},
- {3066, {wxStyledTextCtrl, setIndent, 1}},
- {3067, {wxStyledTextCtrl, getIndent, 0}},
- {3068, {wxStyledTextCtrl, setUseTabs, 1}},
- {3069, {wxStyledTextCtrl, getUseTabs, 0}},
- {3070, {wxStyledTextCtrl, setLineIndentation, 2}},
- {3071, {wxStyledTextCtrl, getLineIndentation, 1}},
- {3072, {wxStyledTextCtrl, getLineIndentPosition, 1}},
- {3073, {wxStyledTextCtrl, getColumn, 1}},
- {3074, {wxStyledTextCtrl, setUseHorizontalScrollBar, 1}},
- {3075, {wxStyledTextCtrl, getUseHorizontalScrollBar, 0}},
- {3076, {wxStyledTextCtrl, setIndentationGuides, 1}},
- {3077, {wxStyledTextCtrl, getIndentationGuides, 0}},
- {3078, {wxStyledTextCtrl, setHighlightGuide, 1}},
- {3079, {wxStyledTextCtrl, getHighlightGuide, 0}},
- {3080, {wxStyledTextCtrl, getLineEndPosition, 1}},
- {3081, {wxStyledTextCtrl, getCodePage, 0}},
- {3082, {wxStyledTextCtrl, getCaretForeground, 0}},
- {3083, {wxStyledTextCtrl, getReadOnly, 0}},
- {3084, {wxStyledTextCtrl, setCurrentPos, 1}},
- {3085, {wxStyledTextCtrl, setSelectionStart, 1}},
- {3086, {wxStyledTextCtrl, getSelectionStart, 0}},
- {3087, {wxStyledTextCtrl, setSelectionEnd, 1}},
- {3088, {wxStyledTextCtrl, getSelectionEnd, 0}},
- {3089, {wxStyledTextCtrl, setPrintMagnification, 1}},
- {3090, {wxStyledTextCtrl, getPrintMagnification, 0}},
- {3091, {wxStyledTextCtrl, setPrintColourMode, 1}},
- {3092, {wxStyledTextCtrl, getPrintColourMode, 0}},
- {3093, {wxStyledTextCtrl, findText, 4}},
- {3094, {wxStyledTextCtrl, formatRange, 7}},
- {3095, {wxStyledTextCtrl, getFirstVisibleLine, 0}},
- {3096, {wxStyledTextCtrl, getLine, 1}},
- {3097, {wxStyledTextCtrl, getLineCount, 0}},
- {3098, {wxStyledTextCtrl, setMarginLeft, 1}},
- {3099, {wxStyledTextCtrl, getMarginLeft, 0}},
- {3100, {wxStyledTextCtrl, setMarginRight, 1}},
- {3101, {wxStyledTextCtrl, getMarginRight, 0}},
- {3102, {wxStyledTextCtrl, getModify, 0}},
- {3103, {wxStyledTextCtrl, setSelection, 2}},
- {3104, {wxStyledTextCtrl, getSelectedText, 0}},
- {3105, {wxStyledTextCtrl, getTextRange, 2}},
- {3106, {wxStyledTextCtrl, hideSelection, 1}},
- {3107, {wxStyledTextCtrl, lineFromPosition, 1}},
- {3108, {wxStyledTextCtrl, positionFromLine, 1}},
- {3109, {wxStyledTextCtrl, lineScroll, 2}},
- {3110, {wxStyledTextCtrl, ensureCaretVisible, 0}},
- {3111, {wxStyledTextCtrl, replaceSelection, 1}},
- {3112, {wxStyledTextCtrl, setReadOnly, 1}},
- {3113, {wxStyledTextCtrl, canPaste, 0}},
- {3114, {wxStyledTextCtrl, canUndo, 0}},
- {3115, {wxStyledTextCtrl, emptyUndoBuffer, 0}},
- {3116, {wxStyledTextCtrl, undo, 0}},
- {3117, {wxStyledTextCtrl, cut, 0}},
- {3118, {wxStyledTextCtrl, copy, 0}},
- {3119, {wxStyledTextCtrl, paste, 0}},
- {3120, {wxStyledTextCtrl, clear, 0}},
- {3121, {wxStyledTextCtrl, setText, 1}},
- {3122, {wxStyledTextCtrl, getText, 0}},
- {3123, {wxStyledTextCtrl, getTextLength, 0}},
- {3124, {wxStyledTextCtrl, getOvertype, 0}},
- {3125, {wxStyledTextCtrl, setCaretWidth, 1}},
- {3126, {wxStyledTextCtrl, getCaretWidth, 0}},
- {3127, {wxStyledTextCtrl, setTargetStart, 1}},
- {3128, {wxStyledTextCtrl, getTargetStart, 0}},
- {3129, {wxStyledTextCtrl, setTargetEnd, 1}},
- {3130, {wxStyledTextCtrl, getTargetEnd, 0}},
- {3131, {wxStyledTextCtrl, replaceTarget, 1}},
- {3132, {wxStyledTextCtrl, searchInTarget, 1}},
- {3133, {wxStyledTextCtrl, setSearchFlags, 1}},
- {3134, {wxStyledTextCtrl, getSearchFlags, 0}},
- {3135, {wxStyledTextCtrl, callTipShow, 2}},
- {3136, {wxStyledTextCtrl, callTipCancel, 0}},
- {3137, {wxStyledTextCtrl, callTipActive, 0}},
- {3138, {wxStyledTextCtrl, callTipPosAtStart, 0}},
- {3139, {wxStyledTextCtrl, callTipSetHighlight, 2}},
- {3140, {wxStyledTextCtrl, callTipSetBackground, 1}},
- {3141, {wxStyledTextCtrl, callTipSetForeground, 1}},
- {3142, {wxStyledTextCtrl, callTipSetForegroundHighlight, 1}},
- {3143, {wxStyledTextCtrl, callTipUseStyle, 1}},
- {3144, {wxStyledTextCtrl, visibleFromDocLine, 1}},
- {3145, {wxStyledTextCtrl, docLineFromVisible, 1}},
- {3146, {wxStyledTextCtrl, wrapCount, 1}},
- {3147, {wxStyledTextCtrl, setFoldLevel, 2}},
- {3148, {wxStyledTextCtrl, getFoldLevel, 1}},
- {3149, {wxStyledTextCtrl, getLastChild, 2}},
- {3150, {wxStyledTextCtrl, getFoldParent, 1}},
- {3151, {wxStyledTextCtrl, showLines, 2}},
- {3152, {wxStyledTextCtrl, hideLines, 2}},
- {3153, {wxStyledTextCtrl, getLineVisible, 1}},
- {3154, {wxStyledTextCtrl, setFoldExpanded, 2}},
- {3155, {wxStyledTextCtrl, getFoldExpanded, 1}},
- {3156, {wxStyledTextCtrl, toggleFold, 1}},
- {3157, {wxStyledTextCtrl, ensureVisible, 1}},
- {3158, {wxStyledTextCtrl, setFoldFlags, 1}},
- {3159, {wxStyledTextCtrl, ensureVisibleEnforcePolicy, 1}},
- {3160, {wxStyledTextCtrl, setTabIndents, 1}},
- {3161, {wxStyledTextCtrl, getTabIndents, 0}},
- {3162, {wxStyledTextCtrl, setBackSpaceUnIndents, 1}},
- {3163, {wxStyledTextCtrl, getBackSpaceUnIndents, 0}},
- {3164, {wxStyledTextCtrl, setMouseDwellTime, 1}},
- {3165, {wxStyledTextCtrl, getMouseDwellTime, 0}},
- {3166, {wxStyledTextCtrl, wordStartPosition, 2}},
- {3167, {wxStyledTextCtrl, wordEndPosition, 2}},
- {3168, {wxStyledTextCtrl, setWrapMode, 1}},
- {3169, {wxStyledTextCtrl, getWrapMode, 0}},
- {3170, {wxStyledTextCtrl, setWrapVisualFlags, 1}},
- {3171, {wxStyledTextCtrl, getWrapVisualFlags, 0}},
- {3172, {wxStyledTextCtrl, setWrapVisualFlagsLocation, 1}},
- {3173, {wxStyledTextCtrl, getWrapVisualFlagsLocation, 0}},
- {3174, {wxStyledTextCtrl, setWrapStartIndent, 1}},
- {3175, {wxStyledTextCtrl, getWrapStartIndent, 0}},
- {3176, {wxStyledTextCtrl, setLayoutCache, 1}},
- {3177, {wxStyledTextCtrl, getLayoutCache, 0}},
- {3178, {wxStyledTextCtrl, setScrollWidth, 1}},
- {3179, {wxStyledTextCtrl, getScrollWidth, 0}},
- {3180, {wxStyledTextCtrl, textWidth, 2}},
- {3181, {wxStyledTextCtrl, getEndAtLastLine, 0}},
- {3182, {wxStyledTextCtrl, textHeight, 1}},
- {3183, {wxStyledTextCtrl, setUseVerticalScrollBar, 1}},
- {3184, {wxStyledTextCtrl, getUseVerticalScrollBar, 0}},
- {3185, {wxStyledTextCtrl, appendText, 1}},
- {3186, {wxStyledTextCtrl, getTwoPhaseDraw, 0}},
- {3187, {wxStyledTextCtrl, setTwoPhaseDraw, 1}},
- {3188, {wxStyledTextCtrl, targetFromSelection, 0}},
- {3189, {wxStyledTextCtrl, linesJoin, 0}},
- {3190, {wxStyledTextCtrl, linesSplit, 1}},
- {3191, {wxStyledTextCtrl, setFoldMarginColour, 2}},
- {3192, {wxStyledTextCtrl, setFoldMarginHiColour, 2}},
- {3193, {wxStyledTextCtrl, lineDown, 0}},
- {3194, {wxStyledTextCtrl, lineDownExtend, 0}},
- {3195, {wxStyledTextCtrl, lineUp, 0}},
- {3196, {wxStyledTextCtrl, lineUpExtend, 0}},
- {3197, {wxStyledTextCtrl, charLeft, 0}},
- {3198, {wxStyledTextCtrl, charLeftExtend, 0}},
- {3199, {wxStyledTextCtrl, charRight, 0}},
- {3200, {wxStyledTextCtrl, charRightExtend, 0}},
- {3201, {wxStyledTextCtrl, wordLeft, 0}},
- {3202, {wxStyledTextCtrl, wordLeftExtend, 0}},
- {3203, {wxStyledTextCtrl, wordRight, 0}},
- {3204, {wxStyledTextCtrl, wordRightExtend, 0}},
- {3205, {wxStyledTextCtrl, home, 0}},
- {3206, {wxStyledTextCtrl, homeExtend, 0}},
- {3207, {wxStyledTextCtrl, lineEnd, 0}},
- {3208, {wxStyledTextCtrl, lineEndExtend, 0}},
- {3209, {wxStyledTextCtrl, documentStart, 0}},
- {3210, {wxStyledTextCtrl, documentStartExtend, 0}},
- {3211, {wxStyledTextCtrl, documentEnd, 0}},
- {3212, {wxStyledTextCtrl, documentEndExtend, 0}},
- {3213, {wxStyledTextCtrl, pageUp, 0}},
- {3214, {wxStyledTextCtrl, pageUpExtend, 0}},
- {3215, {wxStyledTextCtrl, pageDown, 0}},
- {3216, {wxStyledTextCtrl, pageDownExtend, 0}},
- {3217, {wxStyledTextCtrl, editToggleOvertype, 0}},
- {3218, {wxStyledTextCtrl, cancel, 0}},
- {3219, {wxStyledTextCtrl, deleteBack, 0}},
- {3220, {wxStyledTextCtrl, tab, 0}},
- {3221, {wxStyledTextCtrl, backTab, 0}},
- {3222, {wxStyledTextCtrl, newLine, 0}},
- {3223, {wxStyledTextCtrl, formFeed, 0}},
- {3224, {wxStyledTextCtrl, vCHome, 0}},
- {3225, {wxStyledTextCtrl, vCHomeExtend, 0}},
- {3226, {wxStyledTextCtrl, zoomIn, 0}},
- {3227, {wxStyledTextCtrl, zoomOut, 0}},
- {3228, {wxStyledTextCtrl, delWordLeft, 0}},
- {3229, {wxStyledTextCtrl, delWordRight, 0}},
- {3230, {wxStyledTextCtrl, lineCut, 0}},
- {3231, {wxStyledTextCtrl, lineDelete, 0}},
- {3232, {wxStyledTextCtrl, lineTranspose, 0}},
- {3233, {wxStyledTextCtrl, lineDuplicate, 0}},
- {3234, {wxStyledTextCtrl, lowerCase, 0}},
- {3235, {wxStyledTextCtrl, upperCase, 0}},
- {3236, {wxStyledTextCtrl, lineScrollDown, 0}},
- {3237, {wxStyledTextCtrl, lineScrollUp, 0}},
- {3238, {wxStyledTextCtrl, deleteBackNotLine, 0}},
- {3239, {wxStyledTextCtrl, homeDisplay, 0}},
- {3240, {wxStyledTextCtrl, homeDisplayExtend, 0}},
- {3241, {wxStyledTextCtrl, lineEndDisplay, 0}},
- {3242, {wxStyledTextCtrl, lineEndDisplayExtend, 0}},
- {3243, {wxStyledTextCtrl, homeWrapExtend, 0}},
- {3244, {wxStyledTextCtrl, lineEndWrap, 0}},
- {3245, {wxStyledTextCtrl, lineEndWrapExtend, 0}},
- {3246, {wxStyledTextCtrl, vCHomeWrap, 0}},
- {3247, {wxStyledTextCtrl, vCHomeWrapExtend, 0}},
- {3248, {wxStyledTextCtrl, lineCopy, 0}},
- {3249, {wxStyledTextCtrl, moveCaretInsideView, 0}},
- {3250, {wxStyledTextCtrl, lineLength, 1}},
- {3251, {wxStyledTextCtrl, braceHighlight, 2}},
- {3252, {wxStyledTextCtrl, braceBadLight, 1}},
- {3253, {wxStyledTextCtrl, braceMatch, 1}},
- {3254, {wxStyledTextCtrl, getViewEOL, 0}},
- {3255, {wxStyledTextCtrl, setViewEOL, 1}},
- {3256, {wxStyledTextCtrl, setModEventMask, 1}},
- {3257, {wxStyledTextCtrl, getEdgeColumn, 0}},
- {3258, {wxStyledTextCtrl, setEdgeColumn, 1}},
- {3259, {wxStyledTextCtrl, getEdgeMode, 0}},
- {3260, {wxStyledTextCtrl, getEdgeColour, 0}},
- {3261, {wxStyledTextCtrl, setEdgeColour, 1}},
- {3262, {wxStyledTextCtrl, searchAnchor, 0}},
- {3263, {wxStyledTextCtrl, searchNext, 2}},
- {3264, {wxStyledTextCtrl, searchPrev, 2}},
- {3265, {wxStyledTextCtrl, linesOnScreen, 0}},
- {3266, {wxStyledTextCtrl, usePopUp, 1}},
- {3267, {wxStyledTextCtrl, selectionIsRectangle, 0}},
- {3268, {wxStyledTextCtrl, setZoom, 1}},
- {3269, {wxStyledTextCtrl, getZoom, 0}},
- {3270, {wxStyledTextCtrl, getModEventMask, 0}},
- {3271, {wxStyledTextCtrl, setSTCFocus, 1}},
- {3272, {wxStyledTextCtrl, getSTCFocus, 0}},
- {3273, {wxStyledTextCtrl, setStatus, 1}},
- {3274, {wxStyledTextCtrl, getStatus, 0}},
- {3275, {wxStyledTextCtrl, setMouseDownCaptures, 1}},
- {3276, {wxStyledTextCtrl, getMouseDownCaptures, 0}},
- {3277, {wxStyledTextCtrl, setSTCCursor, 1}},
- {3278, {wxStyledTextCtrl, getSTCCursor, 0}},
- {3279, {wxStyledTextCtrl, setControlCharSymbol, 1}},
- {3280, {wxStyledTextCtrl, getControlCharSymbol, 0}},
- {3281, {wxStyledTextCtrl, wordPartLeft, 0}},
- {3282, {wxStyledTextCtrl, wordPartLeftExtend, 0}},
- {3283, {wxStyledTextCtrl, wordPartRight, 0}},
- {3284, {wxStyledTextCtrl, wordPartRightExtend, 0}},
- {3285, {wxStyledTextCtrl, setVisiblePolicy, 2}},
- {3286, {wxStyledTextCtrl, delLineLeft, 0}},
- {3287, {wxStyledTextCtrl, delLineRight, 0}},
- {3288, {wxStyledTextCtrl, getXOffset, 0}},
- {3289, {wxStyledTextCtrl, chooseCaretX, 0}},
- {3290, {wxStyledTextCtrl, setXCaretPolicy, 2}},
- {3291, {wxStyledTextCtrl, setYCaretPolicy, 2}},
- {3292, {wxStyledTextCtrl, getPrintWrapMode, 0}},
- {3293, {wxStyledTextCtrl, setHotspotActiveForeground, 2}},
- {3294, {wxStyledTextCtrl, setHotspotActiveBackground, 2}},
- {3295, {wxStyledTextCtrl, setHotspotActiveUnderline, 1}},
- {3296, {wxStyledTextCtrl, setHotspotSingleLine, 1}},
- {3297, {wxStyledTextCtrl, paraDownExtend, 0}},
- {3298, {wxStyledTextCtrl, paraUp, 0}},
- {3299, {wxStyledTextCtrl, paraUpExtend, 0}},
- {3300, {wxStyledTextCtrl, positionBefore, 1}},
- {3301, {wxStyledTextCtrl, positionAfter, 1}},
- {3302, {wxStyledTextCtrl, copyRange, 2}},
- {3303, {wxStyledTextCtrl, copyText, 2}},
- {3304, {wxStyledTextCtrl, setSelectionMode, 1}},
- {3305, {wxStyledTextCtrl, getSelectionMode, 0}},
- {3306, {wxStyledTextCtrl, lineDownRectExtend, 0}},
- {3307, {wxStyledTextCtrl, lineUpRectExtend, 0}},
- {3308, {wxStyledTextCtrl, charLeftRectExtend, 0}},
- {3309, {wxStyledTextCtrl, charRightRectExtend, 0}},
- {3310, {wxStyledTextCtrl, homeRectExtend, 0}},
- {3311, {wxStyledTextCtrl, vCHomeRectExtend, 0}},
- {3312, {wxStyledTextCtrl, lineEndRectExtend, 0}},
- {3313, {wxStyledTextCtrl, pageUpRectExtend, 0}},
- {3314, {wxStyledTextCtrl, pageDownRectExtend, 0}},
- {3315, {wxStyledTextCtrl, stutteredPageUp, 0}},
- {3316, {wxStyledTextCtrl, stutteredPageUpExtend, 0}},
- {3317, {wxStyledTextCtrl, stutteredPageDown, 0}},
- {3318, {wxStyledTextCtrl, stutteredPageDownExtend, 0}},
- {3319, {wxStyledTextCtrl, wordLeftEnd, 0}},
- {3320, {wxStyledTextCtrl, wordLeftEndExtend, 0}},
- {3321, {wxStyledTextCtrl, wordRightEnd, 0}},
- {3322, {wxStyledTextCtrl, wordRightEndExtend, 0}},
- {3323, {wxStyledTextCtrl, setWhitespaceChars, 1}},
- {3324, {wxStyledTextCtrl, setCharsDefault, 0}},
- {3325, {wxStyledTextCtrl, autoCompGetCurrent, 0}},
- {3326, {wxStyledTextCtrl, allocate, 1}},
- {3327, {wxStyledTextCtrl, findColumn, 2}},
- {3328, {wxStyledTextCtrl, getCaretSticky, 0}},
- {3329, {wxStyledTextCtrl, setCaretSticky, 1}},
- {3330, {wxStyledTextCtrl, toggleCaretSticky, 0}},
- {3331, {wxStyledTextCtrl, setPasteConvertEndings, 1}},
- {3332, {wxStyledTextCtrl, getPasteConvertEndings, 0}},
- {3333, {wxStyledTextCtrl, selectionDuplicate, 0}},
- {3334, {wxStyledTextCtrl, setCaretLineBackAlpha, 1}},
- {3335, {wxStyledTextCtrl, getCaretLineBackAlpha, 0}},
- {3336, {wxStyledTextCtrl, startRecord, 0}},
- {3337, {wxStyledTextCtrl, stopRecord, 0}},
- {3338, {wxStyledTextCtrl, setLexer, 1}},
- {3339, {wxStyledTextCtrl, getLexer, 0}},
- {3340, {wxStyledTextCtrl, colourise, 2}},
- {3341, {wxStyledTextCtrl, setProperty, 2}},
- {3342, {wxStyledTextCtrl, setKeyWords, 2}},
- {3343, {wxStyledTextCtrl, setLexerLanguage, 1}},
- {3344, {wxStyledTextCtrl, getProperty, 1}},
- {3345, {wxStyledTextCtrl, getStyleBitsNeeded, 0}},
- {3346, {wxStyledTextCtrl, getCurrentLine, 0}},
- {3347, {wxStyledTextCtrl, styleSetSpec, 2}},
- {3348, {wxStyledTextCtrl, styleSetFont, 2}},
- {3349, {wxStyledTextCtrl, styleSetFontAttr, 7}},
- {3350, {wxStyledTextCtrl, styleSetCharacterSet, 2}},
- {3351, {wxStyledTextCtrl, styleSetFontEncoding, 2}},
- {3352, {wxStyledTextCtrl, cmdKeyExecute, 1}},
- {3353, {wxStyledTextCtrl, setMargins, 2}},
- {3354, {wxStyledTextCtrl, getSelection, 2}},
- {3355, {wxStyledTextCtrl, pointFromPosition, 1}},
- {3356, {wxStyledTextCtrl, scrollToLine, 1}},
- {3357, {wxStyledTextCtrl, scrollToColumn, 1}},
- {3358, {wxStyledTextCtrl, sendMsg, 2}},
- {3359, {wxStyledTextCtrl, setVScrollBar, 1}},
- {3360, {wxStyledTextCtrl, setHScrollBar, 1}},
- {3361, {wxStyledTextCtrl, getLastKeydownProcessed, 0}},
- {3362, {wxStyledTextCtrl, setLastKeydownProcessed, 1}},
- {3363, {wxStyledTextCtrl, saveFile, 1}},
- {3364, {wxStyledTextCtrl, loadFile, 1}},
- {3365, {wxStyledTextCtrl, doDragOver, 3}},
- {3366, {wxStyledTextCtrl, doDropText, 3}},
- {3367, {wxStyledTextCtrl, getUseAntiAliasing, 0}},
- {3368, {wxStyledTextCtrl, addTextRaw, 1}},
- {3369, {wxStyledTextCtrl, insertTextRaw, 2}},
- {3370, {wxStyledTextCtrl, getCurLineRaw, 1}},
- {3371, {wxStyledTextCtrl, getLineRaw, 1}},
- {3372, {wxStyledTextCtrl, getSelectedTextRaw, 0}},
- {3373, {wxStyledTextCtrl, getTextRangeRaw, 2}},
- {3374, {wxStyledTextCtrl, setTextRaw, 1}},
- {3375, {wxStyledTextCtrl, getTextRaw, 0}},
- {3376, {wxStyledTextCtrl, appendTextRaw, 1}},
- {3377, {wxArtProvider, getBitmap, 2}},
- {3378, {wxArtProvider, getIcon, 2}},
- {3379, {wxTreeEvent, getKeyCode, 0}},
- {3380, {wxTreeEvent, getItem, 0}},
- {3381, {wxTreeEvent, getKeyEvent, 0}},
- {3382, {wxTreeEvent, getLabel, 0}},
- {3383, {wxTreeEvent, getOldItem, 0}},
- {3384, {wxTreeEvent, getPoint, 0}},
- {3385, {wxTreeEvent, isEditCancelled, 0}},
- {3386, {wxTreeEvent, setToolTip, 1}},
- {3387, {wxNotebookEvent, getOldSelection, 0}},
- {3388, {wxNotebookEvent, getSelection, 0}},
- {3389, {wxNotebookEvent, setOldSelection, 1}},
- {3390, {wxNotebookEvent, setSelection, 1}},
- {3391, {wxFileDataObject, new, 0}},
- {3392, {wxFileDataObject, addFile, 1}},
- {3393, {wxFileDataObject, getFilenames, 0}},
- {3394, {wxFileDataObject, 'Destroy', undefined}},
- {3395, {wxTextDataObject, new, 1}},
- {3396, {wxTextDataObject, getTextLength, 0}},
- {3397, {wxTextDataObject, getText, 0}},
- {3398, {wxTextDataObject, setText, 1}},
- {3399, {wxTextDataObject, 'Destroy', undefined}},
- {3400, {wxBitmapDataObject, new_1_1, 1}},
- {3401, {wxBitmapDataObject, new_1_0, 1}},
- {3402, {wxBitmapDataObject, getBitmap, 0}},
- {3403, {wxBitmapDataObject, setBitmap, 1}},
- {3404, {wxBitmapDataObject, 'Destroy', undefined}},
- {3406, {wxClipboard, new, 0}},
- {3407, {wxClipboard, destruct, 0}},
- {3408, {wxClipboard, addData, 1}},
- {3409, {wxClipboard, clear, 0}},
- {3410, {wxClipboard, close, 0}},
- {3411, {wxClipboard, flush, 0}},
- {3412, {wxClipboard, getData, 1}},
- {3413, {wxClipboard, isOpened, 0}},
- {3414, {wxClipboard, open, 0}},
- {3415, {wxClipboard, setData, 1}},
- {3417, {wxClipboard, usePrimarySelection, 1}},
- {3418, {wxClipboard, isSupported, 1}},
- {3419, {wxClipboard, get, 0}},
- {3420, {wxSpinEvent, getPosition, 0}},
- {3421, {wxSpinEvent, setPosition, 1}},
- {3422, {wxSplitterWindow, new_0, 0}},
- {3423, {wxSplitterWindow, new_2, 2}},
- {3424, {wxSplitterWindow, destruct, 0}},
- {3425, {wxSplitterWindow, create, 2}},
- {3426, {wxSplitterWindow, getMinimumPaneSize, 0}},
- {3427, {wxSplitterWindow, getSashGravity, 0}},
- {3428, {wxSplitterWindow, getSashPosition, 0}},
- {3429, {wxSplitterWindow, getSplitMode, 0}},
- {3430, {wxSplitterWindow, getWindow1, 0}},
- {3431, {wxSplitterWindow, getWindow2, 0}},
- {3432, {wxSplitterWindow, initialize, 1}},
- {3433, {wxSplitterWindow, isSplit, 0}},
- {3434, {wxSplitterWindow, replaceWindow, 2}},
- {3435, {wxSplitterWindow, setSashGravity, 1}},
- {3436, {wxSplitterWindow, setSashPosition, 2}},
- {3437, {wxSplitterWindow, setSashSize, 1}},
- {3438, {wxSplitterWindow, setMinimumPaneSize, 1}},
- {3439, {wxSplitterWindow, setSplitMode, 1}},
- {3440, {wxSplitterWindow, splitHorizontally, 3}},
- {3441, {wxSplitterWindow, splitVertically, 3}},
- {3442, {wxSplitterWindow, unsplit, 1}},
- {3443, {wxSplitterWindow, updateSize, 0}},
- {3444, {wxSplitterEvent, getSashPosition, 0}},
- {3445, {wxSplitterEvent, getX, 0}},
- {3446, {wxSplitterEvent, getY, 0}},
- {3447, {wxSplitterEvent, getWindowBeingRemoved, 0}},
- {3448, {wxSplitterEvent, setSashPosition, 1}},
- {3449, {wxHtmlWindow, new_0, 0}},
- {3450, {wxHtmlWindow, new_2, 2}},
- {3451, {wxHtmlWindow, appendToPage, 1}},
- {3452, {wxHtmlWindow, getOpenedAnchor, 0}},
- {3453, {wxHtmlWindow, getOpenedPage, 0}},
- {3454, {wxHtmlWindow, getOpenedPageTitle, 0}},
- {3455, {wxHtmlWindow, getRelatedFrame, 0}},
- {3456, {wxHtmlWindow, historyBack, 0}},
- {3457, {wxHtmlWindow, historyCanBack, 0}},
- {3458, {wxHtmlWindow, historyCanForward, 0}},
- {3459, {wxHtmlWindow, historyClear, 0}},
- {3460, {wxHtmlWindow, historyForward, 0}},
- {3461, {wxHtmlWindow, loadFile, 1}},
- {3462, {wxHtmlWindow, loadPage, 1}},
- {3463, {wxHtmlWindow, selectAll, 0}},
- {3464, {wxHtmlWindow, selectionToText, 0}},
- {3465, {wxHtmlWindow, selectLine, 1}},
- {3466, {wxHtmlWindow, selectWord, 1}},
- {3467, {wxHtmlWindow, setBorders, 1}},
- {3468, {wxHtmlWindow, setFonts, 3}},
- {3469, {wxHtmlWindow, setPage, 1}},
- {3470, {wxHtmlWindow, setRelatedFrame, 2}},
- {3471, {wxHtmlWindow, setRelatedStatusBar, 1}},
- {3472, {wxHtmlWindow, toText, 0}},
- {3473, {wxHtmlWindow, 'Destroy', undefined}},
- {3474, {wxHtmlLinkEvent, getLinkInfo, 0}},
- {3475, {wxAuiNotebookEvent, setSelection, 1}},
- {3476, {wxAuiNotebookEvent, getSelection, 0}},
- {3477, {wxAuiNotebookEvent, setOldSelection, 1}},
- {3478, {wxAuiNotebookEvent, getOldSelection, 0}},
- {3479, {wxAuiNotebookEvent, setDragSource, 1}},
- {3480, {wxAuiNotebookEvent, getDragSource, 0}},
- {3481, {wxAuiManagerEvent, setManager, 1}},
- {3482, {wxAuiManagerEvent, getManager, 0}},
- {3483, {wxAuiManagerEvent, setPane, 1}},
- {3484, {wxAuiManagerEvent, getPane, 0}},
- {3485, {wxAuiManagerEvent, setButton, 1}},
- {3486, {wxAuiManagerEvent, getButton, 0}},
- {3487, {wxAuiManagerEvent, setDC, 1}},
- {3488, {wxAuiManagerEvent, getDC, 0}},
- {3489, {wxAuiManagerEvent, veto, 1}},
- {3490, {wxAuiManagerEvent, getVeto, 0}},
- {3491, {wxAuiManagerEvent, setCanVeto, 1}},
- {3492, {wxAuiManagerEvent, canVeto, 0}},
- {3493, {wxLogNull, new, 0}},
- {3494, {wxLogNull, 'Destroy', undefined}},
+ {2010, {wxTreeCtrl, editLabel, 1}},
+ {2011, {wxTreeCtrl, ensureVisible, 1}},
+ {2012, {wxTreeCtrl, expand, 1}},
+ {2013, {wxTreeCtrl, getBoundingRect, 3}},
+ {2015, {wxTreeCtrl, getChildrenCount, 2}},
+ {2016, {wxTreeCtrl, getCount, 0}},
+ {2017, {wxTreeCtrl, getEditControl, 0}},
+ {2018, {wxTreeCtrl, getFirstChild, 2}},
+ {2019, {wxTreeCtrl, getNextChild, 2}},
+ {2020, {wxTreeCtrl, getFirstVisibleItem, 0}},
+ {2021, {wxTreeCtrl, getImageList, 0}},
+ {2022, {wxTreeCtrl, getIndent, 0}},
+ {2023, {wxTreeCtrl, getItemBackgroundColour, 1}},
+ {2024, {wxTreeCtrl, getItemData, 1}},
+ {2025, {wxTreeCtrl, getItemFont, 1}},
+ {2026, {wxTreeCtrl, getItemImage_1, 1}},
+ {2027, {wxTreeCtrl, getItemImage_2, 2}},
+ {2028, {wxTreeCtrl, getItemText, 1}},
+ {2029, {wxTreeCtrl, getItemTextColour, 1}},
+ {2030, {wxTreeCtrl, getLastChild, 1}},
+ {2031, {wxTreeCtrl, getNextSibling, 1}},
+ {2032, {wxTreeCtrl, getNextVisible, 1}},
+ {2033, {wxTreeCtrl, getItemParent, 1}},
+ {2034, {wxTreeCtrl, getPrevSibling, 1}},
+ {2035, {wxTreeCtrl, getPrevVisible, 1}},
+ {2036, {wxTreeCtrl, getRootItem, 0}},
+ {2037, {wxTreeCtrl, getSelection, 0}},
+ {2038, {wxTreeCtrl, getSelections, 1}},
+ {2039, {wxTreeCtrl, getStateImageList, 0}},
+ {2040, {wxTreeCtrl, hitTest, 1}},
+ {2042, {wxTreeCtrl, insertItem, 4}},
+ {2043, {wxTreeCtrl, isBold, 1}},
+ {2044, {wxTreeCtrl, isExpanded, 1}},
+ {2045, {wxTreeCtrl, isSelected, 1}},
+ {2046, {wxTreeCtrl, isVisible, 1}},
+ {2047, {wxTreeCtrl, itemHasChildren, 1}},
+ {2048, {wxTreeCtrl, prependItem, 3}},
+ {2049, {wxTreeCtrl, scrollTo, 1}},
+ {2050, {wxTreeCtrl, selectItem_1, 1}},
+ {2051, {wxTreeCtrl, selectItem_2, 2}},
+ {2052, {wxTreeCtrl, setIndent, 1}},
+ {2053, {wxTreeCtrl, setImageList, 1}},
+ {2054, {wxTreeCtrl, setItemBackgroundColour, 2}},
+ {2055, {wxTreeCtrl, setItemBold, 2}},
+ {2056, {wxTreeCtrl, setItemData, 2}},
+ {2057, {wxTreeCtrl, setItemDropHighlight, 2}},
+ {2058, {wxTreeCtrl, setItemFont, 2}},
+ {2059, {wxTreeCtrl, setItemHasChildren, 2}},
+ {2060, {wxTreeCtrl, setItemImage_2, 2}},
+ {2061, {wxTreeCtrl, setItemImage_3, 3}},
+ {2062, {wxTreeCtrl, setItemText, 2}},
+ {2063, {wxTreeCtrl, setItemTextColour, 2}},
+ {2064, {wxTreeCtrl, setStateImageList, 1}},
+ {2065, {wxTreeCtrl, setWindowStyle, 1}},
+ {2066, {wxTreeCtrl, sortChildren, 1}},
+ {2067, {wxTreeCtrl, toggle, 1}},
+ {2068, {wxTreeCtrl, toggleItemSelection, 1}},
+ {2069, {wxTreeCtrl, unselect, 0}},
+ {2070, {wxTreeCtrl, unselectAll, 0}},
+ {2071, {wxTreeCtrl, unselectItem, 1}},
+ {2072, {wxScrollBar, new_0, 0}},
+ {2073, {wxScrollBar, new_3, 3}},
+ {2074, {wxScrollBar, destruct, 0}},
+ {2075, {wxScrollBar, create, 3}},
+ {2076, {wxScrollBar, getRange, 0}},
+ {2077, {wxScrollBar, getPageSize, 0}},
+ {2078, {wxScrollBar, getThumbPosition, 0}},
+ {2079, {wxScrollBar, getThumbSize, 0}},
+ {2080, {wxScrollBar, setThumbPosition, 1}},
+ {2081, {wxScrollBar, setScrollbar, 5}},
+ {2083, {wxSpinButton, new_2, 2}},
+ {2084, {wxSpinButton, new_0, 0}},
+ {2085, {wxSpinButton, create, 2}},
+ {2086, {wxSpinButton, getMax, 0}},
+ {2087, {wxSpinButton, getMin, 0}},
+ {2088, {wxSpinButton, getValue, 0}},
+ {2089, {wxSpinButton, setRange, 2}},
+ {2090, {wxSpinButton, setValue, 1}},
+ {2091, {wxSpinButton, 'Destroy', undefined}},
+ {2092, {wxSpinCtrl, new_0, 0}},
+ {2093, {wxSpinCtrl, new_2, 2}},
+ {2095, {wxSpinCtrl, create, 2}},
+ {2098, {wxSpinCtrl, setValue_1_1, 1}},
+ {2099, {wxSpinCtrl, setValue_1_0, 1}},
+ {2101, {wxSpinCtrl, getValue, 0}},
+ {2103, {wxSpinCtrl, setRange, 2}},
+ {2104, {wxSpinCtrl, setSelection, 2}},
+ {2106, {wxSpinCtrl, getMin, 0}},
+ {2108, {wxSpinCtrl, getMax, 0}},
+ {2109, {wxSpinCtrl, 'Destroy', undefined}},
+ {2110, {wxStaticText, new_0, 0}},
+ {2111, {wxStaticText, new_4, 4}},
+ {2112, {wxStaticText, create, 4}},
+ {2113, {wxStaticText, getLabel, 0}},
+ {2114, {wxStaticText, setLabel, 1}},
+ {2115, {wxStaticText, wrap, 1}},
+ {2116, {wxStaticText, 'Destroy', undefined}},
+ {2117, {wxStaticBitmap, new_0, 0}},
+ {2118, {wxStaticBitmap, new_4, 4}},
+ {2119, {wxStaticBitmap, create, 4}},
+ {2120, {wxStaticBitmap, getBitmap, 0}},
+ {2121, {wxStaticBitmap, setBitmap, 1}},
+ {2122, {wxStaticBitmap, 'Destroy', undefined}},
+ {2123, {wxRadioBox, new, 7}},
+ {2125, {wxRadioBox, destruct, 0}},
+ {2126, {wxRadioBox, create, 7}},
+ {2127, {wxRadioBox, enable_2, 2}},
+ {2128, {wxRadioBox, enable_1, 1}},
+ {2129, {wxRadioBox, getSelection, 0}},
+ {2130, {wxRadioBox, getString, 1}},
+ {2131, {wxRadioBox, setSelection, 1}},
+ {2132, {wxRadioBox, show_2, 2}},
+ {2133, {wxRadioBox, show_1, 1}},
+ {2134, {wxRadioBox, getColumnCount, 0}},
+ {2135, {wxRadioBox, getItemHelpText, 1}},
+ {2136, {wxRadioBox, getItemToolTip, 1}},
+ {2138, {wxRadioBox, getItemFromPoint, 1}},
+ {2139, {wxRadioBox, getRowCount, 0}},
+ {2140, {wxRadioBox, isItemEnabled, 1}},
+ {2141, {wxRadioBox, isItemShown, 1}},
+ {2142, {wxRadioBox, setItemHelpText, 2}},
+ {2143, {wxRadioBox, setItemToolTip, 2}},
+ {2144, {wxRadioButton, new_0, 0}},
+ {2145, {wxRadioButton, new_4, 4}},
+ {2146, {wxRadioButton, create, 4}},
+ {2147, {wxRadioButton, getValue, 0}},
+ {2148, {wxRadioButton, setValue, 1}},
+ {2149, {wxRadioButton, 'Destroy', undefined}},
+ {2151, {wxSlider, new_6, 6}},
+ {2152, {wxSlider, new_0, 0}},
+ {2153, {wxSlider, create, 6}},
+ {2154, {wxSlider, getLineSize, 0}},
+ {2155, {wxSlider, getMax, 0}},
+ {2156, {wxSlider, getMin, 0}},
+ {2157, {wxSlider, getPageSize, 0}},
+ {2158, {wxSlider, getThumbLength, 0}},
+ {2159, {wxSlider, getValue, 0}},
+ {2160, {wxSlider, setLineSize, 1}},
+ {2161, {wxSlider, setPageSize, 1}},
+ {2162, {wxSlider, setRange, 2}},
+ {2163, {wxSlider, setThumbLength, 1}},
+ {2164, {wxSlider, setValue, 1}},
+ {2165, {wxSlider, 'Destroy', undefined}},
+ {2167, {wxDialog, new_4, 4}},
+ {2168, {wxDialog, new_0, 0}},
+ {2170, {wxDialog, destruct, 0}},
+ {2171, {wxDialog, create, 4}},
+ {2172, {wxDialog, createButtonSizer, 1}},
+ {2173, {wxDialog, createStdDialogButtonSizer, 1}},
+ {2174, {wxDialog, endModal, 1}},
+ {2175, {wxDialog, getAffirmativeId, 0}},
+ {2176, {wxDialog, getReturnCode, 0}},
+ {2177, {wxDialog, isModal, 0}},
+ {2178, {wxDialog, setAffirmativeId, 1}},
+ {2179, {wxDialog, setReturnCode, 1}},
+ {2180, {wxDialog, show, 1}},
+ {2181, {wxDialog, showModal, 0}},
+ {2182, {wxColourDialog, new_0, 0}},
+ {2183, {wxColourDialog, new_2, 2}},
+ {2184, {wxColourDialog, destruct, 0}},
+ {2185, {wxColourDialog, create, 2}},
+ {2186, {wxColourDialog, getColourData, 0}},
+ {2187, {wxColourData, new_0, 0}},
+ {2188, {wxColourData, new_1, 1}},
+ {2189, {wxColourData, destruct, 0}},
+ {2190, {wxColourData, getChooseFull, 0}},
+ {2191, {wxColourData, getColour, 0}},
+ {2193, {wxColourData, getCustomColour, 1}},
+ {2194, {wxColourData, setChooseFull, 1}},
+ {2195, {wxColourData, setColour, 1}},
+ {2196, {wxColourData, setCustomColour, 2}},
+ {2197, {wxPalette, new_0, 0}},
+ {2198, {wxPalette, new_4, 4}},
+ {2200, {wxPalette, destruct, 0}},
+ {2201, {wxPalette, create, 4}},
+ {2202, {wxPalette, getColoursCount, 0}},
+ {2203, {wxPalette, getPixel, 3}},
+ {2204, {wxPalette, getRGB, 4}},
+ {2205, {wxPalette, isOk, 0}},
+ {2209, {wxDirDialog, new, 2}},
+ {2210, {wxDirDialog, destruct, 0}},
+ {2211, {wxDirDialog, getPath, 0}},
+ {2212, {wxDirDialog, getMessage, 0}},
+ {2213, {wxDirDialog, setMessage, 1}},
+ {2214, {wxDirDialog, setPath, 1}},
+ {2218, {wxFileDialog, new, 2}},
+ {2219, {wxFileDialog, destruct, 0}},
+ {2220, {wxFileDialog, getDirectory, 0}},
+ {2221, {wxFileDialog, getFilename, 0}},
+ {2222, {wxFileDialog, getFilenames, 1}},
+ {2223, {wxFileDialog, getFilterIndex, 0}},
+ {2224, {wxFileDialog, getMessage, 0}},
+ {2225, {wxFileDialog, getPath, 0}},
+ {2226, {wxFileDialog, getPaths, 1}},
+ {2227, {wxFileDialog, getWildcard, 0}},
+ {2228, {wxFileDialog, setDirectory, 1}},
+ {2229, {wxFileDialog, setFilename, 1}},
+ {2230, {wxFileDialog, setFilterIndex, 1}},
+ {2231, {wxFileDialog, setMessage, 1}},
+ {2232, {wxFileDialog, setPath, 1}},
+ {2233, {wxFileDialog, setWildcard, 1}},
+ {2234, {wxPickerBase, setInternalMargin, 1}},
+ {2235, {wxPickerBase, getInternalMargin, 0}},
+ {2236, {wxPickerBase, setTextCtrlProportion, 1}},
+ {2237, {wxPickerBase, setPickerCtrlProportion, 1}},
+ {2238, {wxPickerBase, getTextCtrlProportion, 0}},
+ {2239, {wxPickerBase, getPickerCtrlProportion, 0}},
+ {2240, {wxPickerBase, hasTextCtrl, 0}},
+ {2241, {wxPickerBase, getTextCtrl, 0}},
+ {2242, {wxPickerBase, isTextCtrlGrowable, 0}},
+ {2243, {wxPickerBase, setPickerCtrlGrowable, 1}},
+ {2244, {wxPickerBase, setTextCtrlGrowable, 1}},
+ {2245, {wxPickerBase, isPickerCtrlGrowable, 0}},
+ {2246, {wxFilePickerCtrl, new_0, 0}},
+ {2247, {wxFilePickerCtrl, new_3, 3}},
+ {2248, {wxFilePickerCtrl, create, 3}},
+ {2249, {wxFilePickerCtrl, getPath, 0}},
+ {2250, {wxFilePickerCtrl, setPath, 1}},
+ {2251, {wxFilePickerCtrl, 'Destroy', undefined}},
+ {2252, {wxDirPickerCtrl, new_0, 0}},
+ {2253, {wxDirPickerCtrl, new_3, 3}},
+ {2254, {wxDirPickerCtrl, create, 3}},
+ {2255, {wxDirPickerCtrl, getPath, 0}},
+ {2256, {wxDirPickerCtrl, setPath, 1}},
+ {2257, {wxDirPickerCtrl, 'Destroy', undefined}},
+ {2258, {wxColourPickerCtrl, new_0, 0}},
+ {2259, {wxColourPickerCtrl, new_3, 3}},
+ {2260, {wxColourPickerCtrl, create, 3}},
+ {2261, {wxColourPickerCtrl, getColour, 0}},
+ {2262, {wxColourPickerCtrl, setColour_1_1, 1}},
+ {2263, {wxColourPickerCtrl, setColour_1_0, 1}},
+ {2264, {wxColourPickerCtrl, 'Destroy', undefined}},
+ {2265, {wxDatePickerCtrl, new_0, 0}},
+ {2266, {wxDatePickerCtrl, new_3, 3}},
+ {2267, {wxDatePickerCtrl, getRange, 2}},
+ {2268, {wxDatePickerCtrl, getValue, 0}},
+ {2269, {wxDatePickerCtrl, setRange, 2}},
+ {2270, {wxDatePickerCtrl, setValue, 1}},
+ {2271, {wxDatePickerCtrl, 'Destroy', undefined}},
+ {2272, {wxFontPickerCtrl, new_0, 0}},
+ {2273, {wxFontPickerCtrl, new_3, 3}},
+ {2274, {wxFontPickerCtrl, create, 3}},
+ {2275, {wxFontPickerCtrl, getSelectedFont, 0}},
+ {2276, {wxFontPickerCtrl, setSelectedFont, 1}},
+ {2277, {wxFontPickerCtrl, getMaxPointSize, 0}},
+ {2278, {wxFontPickerCtrl, setMaxPointSize, 1}},
+ {2279, {wxFontPickerCtrl, 'Destroy', undefined}},
+ {2282, {wxFindReplaceDialog, new_0, 0}},
+ {2283, {wxFindReplaceDialog, new_4, 4}},
+ {2284, {wxFindReplaceDialog, destruct, 0}},
+ {2285, {wxFindReplaceDialog, create, 4}},
+ {2286, {wxFindReplaceDialog, getData, 0}},
+ {2287, {wxFindReplaceData, new_0, 0}},
+ {2288, {wxFindReplaceData, new_1, 1}},
+ {2289, {wxFindReplaceData, getFindString, 0}},
+ {2290, {wxFindReplaceData, getReplaceString, 0}},
+ {2291, {wxFindReplaceData, getFlags, 0}},
+ {2292, {wxFindReplaceData, setFlags, 1}},
+ {2293, {wxFindReplaceData, setFindString, 1}},
+ {2294, {wxFindReplaceData, setReplaceString, 1}},
+ {2295, {wxFindReplaceData, 'Destroy', undefined}},
+ {2296, {wxMultiChoiceDialog, new_0, 0}},
+ {2298, {wxMultiChoiceDialog, new_5, 5}},
+ {2299, {wxMultiChoiceDialog, getSelections, 0}},
+ {2300, {wxMultiChoiceDialog, setSelections, 1}},
+ {2301, {wxMultiChoiceDialog, 'Destroy', undefined}},
+ {2302, {wxSingleChoiceDialog, new_0, 0}},
+ {2304, {wxSingleChoiceDialog, new_5, 5}},
+ {2305, {wxSingleChoiceDialog, getSelection, 0}},
+ {2306, {wxSingleChoiceDialog, getStringSelection, 0}},
+ {2307, {wxSingleChoiceDialog, setSelection, 1}},
+ {2308, {wxSingleChoiceDialog, 'Destroy', undefined}},
+ {2309, {wxTextEntryDialog, new, 3}},
+ {2310, {wxTextEntryDialog, getValue, 0}},
+ {2311, {wxTextEntryDialog, setValue, 1}},
+ {2312, {wxTextEntryDialog, 'Destroy', undefined}},
+ {2313, {wxPasswordEntryDialog, new, 3}},
+ {2314, {wxPasswordEntryDialog, 'Destroy', undefined}},
+ {2315, {wxFontData, new_0, 0}},
+ {2316, {wxFontData, new_1, 1}},
+ {2317, {wxFontData, destruct, 0}},
+ {2318, {wxFontData, enableEffects, 1}},
+ {2319, {wxFontData, getAllowSymbols, 0}},
+ {2320, {wxFontData, getColour, 0}},
+ {2321, {wxFontData, getChosenFont, 0}},
+ {2322, {wxFontData, getEnableEffects, 0}},
+ {2323, {wxFontData, getInitialFont, 0}},
+ {2324, {wxFontData, getShowHelp, 0}},
+ {2325, {wxFontData, setAllowSymbols, 1}},
+ {2326, {wxFontData, setChosenFont, 1}},
+ {2327, {wxFontData, setColour, 1}},
+ {2328, {wxFontData, setInitialFont, 1}},
+ {2329, {wxFontData, setRange, 2}},
+ {2330, {wxFontData, setShowHelp, 1}},
+ {2334, {wxFontDialog, new_0, 0}},
+ {2336, {wxFontDialog, new_2, 2}},
+ {2338, {wxFontDialog, create, 2}},
+ {2339, {wxFontDialog, getFontData, 0}},
+ {2341, {wxFontDialog, 'Destroy', undefined}},
+ {2342, {wxProgressDialog, new, 3}},
+ {2343, {wxProgressDialog, destruct, 0}},
+ {2344, {wxProgressDialog, resume, 0}},
+ {2345, {wxProgressDialog, update_2, 2}},
+ {2346, {wxProgressDialog, update_0, 0}},
+ {2347, {wxMessageDialog, new, 3}},
+ {2348, {wxMessageDialog, destruct, 0}},
+ {2349, {wxPageSetupDialog, new, 2}},
+ {2350, {wxPageSetupDialog, destruct, 0}},
+ {2351, {wxPageSetupDialog, getPageSetupData, 0}},
+ {2352, {wxPageSetupDialog, showModal, 0}},
+ {2353, {wxPageSetupDialogData, new_0, 0}},
+ {2354, {wxPageSetupDialogData, new_1_0, 1}},
+ {2355, {wxPageSetupDialogData, new_1_1, 1}},
+ {2356, {wxPageSetupDialogData, destruct, 0}},
+ {2357, {wxPageSetupDialogData, enableHelp, 1}},
+ {2358, {wxPageSetupDialogData, enableMargins, 1}},
+ {2359, {wxPageSetupDialogData, enableOrientation, 1}},
+ {2360, {wxPageSetupDialogData, enablePaper, 1}},
+ {2361, {wxPageSetupDialogData, enablePrinter, 1}},
+ {2362, {wxPageSetupDialogData, getDefaultMinMargins, 0}},
+ {2363, {wxPageSetupDialogData, getEnableMargins, 0}},
+ {2364, {wxPageSetupDialogData, getEnableOrientation, 0}},
+ {2365, {wxPageSetupDialogData, getEnablePaper, 0}},
+ {2366, {wxPageSetupDialogData, getEnablePrinter, 0}},
+ {2367, {wxPageSetupDialogData, getEnableHelp, 0}},
+ {2368, {wxPageSetupDialogData, getDefaultInfo, 0}},
+ {2369, {wxPageSetupDialogData, getMarginTopLeft, 0}},
+ {2370, {wxPageSetupDialogData, getMarginBottomRight, 0}},
+ {2371, {wxPageSetupDialogData, getMinMarginTopLeft, 0}},
+ {2372, {wxPageSetupDialogData, getMinMarginBottomRight, 0}},
+ {2373, {wxPageSetupDialogData, getPaperId, 0}},
+ {2374, {wxPageSetupDialogData, getPaperSize, 0}},
+ {2376, {wxPageSetupDialogData, getPrintData, 0}},
+ {2377, {wxPageSetupDialogData, isOk, 0}},
+ {2378, {wxPageSetupDialogData, setDefaultInfo, 1}},
+ {2379, {wxPageSetupDialogData, setDefaultMinMargins, 1}},
+ {2380, {wxPageSetupDialogData, setMarginTopLeft, 1}},
+ {2381, {wxPageSetupDialogData, setMarginBottomRight, 1}},
+ {2382, {wxPageSetupDialogData, setMinMarginTopLeft, 1}},
+ {2383, {wxPageSetupDialogData, setMinMarginBottomRight, 1}},
+ {2384, {wxPageSetupDialogData, setPaperId, 1}},
+ {2385, {wxPageSetupDialogData, setPaperSize_1_1, 1}},
+ {2386, {wxPageSetupDialogData, setPaperSize_1_0, 1}},
+ {2387, {wxPageSetupDialogData, setPrintData, 1}},
+ {2388, {wxPrintDialog, new_2_0, 2}},
+ {2389, {wxPrintDialog, new_2_1, 2}},
+ {2390, {wxPrintDialog, destruct, 0}},
+ {2391, {wxPrintDialog, getPrintDialogData, 0}},
+ {2392, {wxPrintDialog, getPrintDC, 0}},
+ {2393, {wxPrintDialogData, new_0, 0}},
+ {2394, {wxPrintDialogData, new_1_1, 1}},
+ {2395, {wxPrintDialogData, new_1_0, 1}},
+ {2396, {wxPrintDialogData, destruct, 0}},
+ {2397, {wxPrintDialogData, enableHelp, 1}},
+ {2398, {wxPrintDialogData, enablePageNumbers, 1}},
+ {2399, {wxPrintDialogData, enablePrintToFile, 1}},
+ {2400, {wxPrintDialogData, enableSelection, 1}},
+ {2401, {wxPrintDialogData, getAllPages, 0}},
+ {2402, {wxPrintDialogData, getCollate, 0}},
+ {2403, {wxPrintDialogData, getFromPage, 0}},
+ {2404, {wxPrintDialogData, getMaxPage, 0}},
+ {2405, {wxPrintDialogData, getMinPage, 0}},
+ {2406, {wxPrintDialogData, getNoCopies, 0}},
+ {2407, {wxPrintDialogData, getPrintData, 0}},
+ {2408, {wxPrintDialogData, getPrintToFile, 0}},
+ {2409, {wxPrintDialogData, getSelection, 0}},
+ {2410, {wxPrintDialogData, getToPage, 0}},
+ {2411, {wxPrintDialogData, isOk, 0}},
+ {2412, {wxPrintDialogData, setCollate, 1}},
+ {2413, {wxPrintDialogData, setFromPage, 1}},
+ {2414, {wxPrintDialogData, setMaxPage, 1}},
+ {2415, {wxPrintDialogData, setMinPage, 1}},
+ {2416, {wxPrintDialogData, setNoCopies, 1}},
+ {2417, {wxPrintDialogData, setPrintData, 1}},
+ {2418, {wxPrintDialogData, setPrintToFile, 1}},
+ {2419, {wxPrintDialogData, setSelection, 1}},
+ {2420, {wxPrintDialogData, setToPage, 1}},
+ {2421, {wxPrintData, new_0, 0}},
+ {2422, {wxPrintData, new_1, 1}},
+ {2423, {wxPrintData, destruct, 0}},
+ {2424, {wxPrintData, getCollate, 0}},
+ {2425, {wxPrintData, getBin, 0}},
+ {2426, {wxPrintData, getColour, 0}},
+ {2427, {wxPrintData, getDuplex, 0}},
+ {2428, {wxPrintData, getNoCopies, 0}},
+ {2429, {wxPrintData, getOrientation, 0}},
+ {2430, {wxPrintData, getPaperId, 0}},
+ {2431, {wxPrintData, getPrinterName, 0}},
+ {2432, {wxPrintData, getQuality, 0}},
+ {2433, {wxPrintData, isOk, 0}},
+ {2434, {wxPrintData, setBin, 1}},
+ {2435, {wxPrintData, setCollate, 1}},
+ {2436, {wxPrintData, setColour, 1}},
+ {2437, {wxPrintData, setDuplex, 1}},
+ {2438, {wxPrintData, setNoCopies, 1}},
+ {2439, {wxPrintData, setOrientation, 1}},
+ {2440, {wxPrintData, setPaperId, 1}},
+ {2441, {wxPrintData, setPrinterName, 1}},
+ {2442, {wxPrintData, setQuality, 1}},
+ {2445, {wxPrintPreview, new_2, 2}},
+ {2446, {wxPrintPreview, new_3, 3}},
+ {2448, {wxPrintPreview, destruct, 0}},
+ {2449, {wxPrintPreview, getCanvas, 0}},
+ {2450, {wxPrintPreview, getCurrentPage, 0}},
+ {2451, {wxPrintPreview, getFrame, 0}},
+ {2452, {wxPrintPreview, getMaxPage, 0}},
+ {2453, {wxPrintPreview, getMinPage, 0}},
+ {2454, {wxPrintPreview, getPrintout, 0}},
+ {2455, {wxPrintPreview, getPrintoutForPrinting, 0}},
+ {2456, {wxPrintPreview, isOk, 0}},
+ {2457, {wxPrintPreview, paintPage, 2}},
+ {2458, {wxPrintPreview, print, 1}},
+ {2459, {wxPrintPreview, renderPage, 1}},
+ {2460, {wxPrintPreview, setCanvas, 1}},
+ {2461, {wxPrintPreview, setCurrentPage, 1}},
+ {2462, {wxPrintPreview, setFrame, 1}},
+ {2463, {wxPrintPreview, setPrintout, 1}},
+ {2464, {wxPrintPreview, setZoom, 1}},
+ {2465, {wxPreviewFrame, new, 3}},
+ {2466, {wxPreviewFrame, destruct, 0}},
+ {2467, {wxPreviewFrame, createControlBar, 0}},
+ {2468, {wxPreviewFrame, createCanvas, 0}},
+ {2469, {wxPreviewFrame, initialize, 0}},
+ {2470, {wxPreviewFrame, onCloseWindow, 1}},
+ {2471, {wxPreviewControlBar, new, 4}},
+ {2472, {wxPreviewControlBar, destruct, 0}},
+ {2473, {wxPreviewControlBar, createButtons, 0}},
+ {2474, {wxPreviewControlBar, getPrintPreview, 0}},
+ {2475, {wxPreviewControlBar, getZoomControl, 0}},
+ {2476, {wxPreviewControlBar, setZoomControl, 1}},
+ {2478, {wxPrinter, new, 1}},
+ {2479, {wxPrinter, createAbortWindow, 2}},
+ {2480, {wxPrinter, getAbort, 0}},
+ {2481, {wxPrinter, getLastError, 0}},
+ {2482, {wxPrinter, getPrintDialogData, 0}},
+ {2483, {wxPrinter, print, 3}},
+ {2484, {wxPrinter, printDialog, 1}},
+ {2485, {wxPrinter, reportError, 3}},
+ {2486, {wxPrinter, setup, 1}},
+ {2487, {wxPrinter, 'Destroy', undefined}},
+ {2488, {wxXmlResource, new_1, 1}},
+ {2489, {wxXmlResource, new_2, 2}},
+ {2490, {wxXmlResource, destruct, 0}},
+ {2491, {wxXmlResource, attachUnknownControl, 3}},
+ {2492, {wxXmlResource, clearHandlers, 0}},
+ {2493, {wxXmlResource, compareVersion, 4}},
+ {2494, {wxXmlResource, get, 0}},
+ {2495, {wxXmlResource, getFlags, 0}},
+ {2496, {wxXmlResource, getVersion, 0}},
+ {2497, {wxXmlResource, getXRCID, 2}},
+ {2498, {wxXmlResource, initAllHandlers, 0}},
+ {2499, {wxXmlResource, load, 1}},
+ {2500, {wxXmlResource, loadBitmap, 1}},
+ {2501, {wxXmlResource, loadDialog_2, 2}},
+ {2502, {wxXmlResource, loadDialog_3, 3}},
+ {2503, {wxXmlResource, loadFrame_2, 2}},
+ {2504, {wxXmlResource, loadFrame_3, 3}},
+ {2505, {wxXmlResource, loadIcon, 1}},
+ {2506, {wxXmlResource, loadMenu, 1}},
+ {2507, {wxXmlResource, loadMenuBar_2, 2}},
+ {2508, {wxXmlResource, loadMenuBar_1, 1}},
+ {2509, {wxXmlResource, loadPanel_2, 2}},
+ {2510, {wxXmlResource, loadPanel_3, 3}},
+ {2511, {wxXmlResource, loadToolBar, 2}},
+ {2512, {wxXmlResource, set, 1}},
+ {2513, {wxXmlResource, setFlags, 1}},
+ {2514, {wxXmlResource, unload, 1}},
+ {2515, {wxXmlResource, xrcctrl, 3}},
+ {2516, {wxHtmlEasyPrinting, new, 1}},
+ {2517, {wxHtmlEasyPrinting, destruct, 0}},
+ {2518, {wxHtmlEasyPrinting, getPrintData, 0}},
+ {2519, {wxHtmlEasyPrinting, getPageSetupData, 0}},
+ {2520, {wxHtmlEasyPrinting, previewFile, 1}},
+ {2521, {wxHtmlEasyPrinting, previewText, 2}},
+ {2522, {wxHtmlEasyPrinting, printFile, 1}},
+ {2523, {wxHtmlEasyPrinting, printText, 2}},
+ {2524, {wxHtmlEasyPrinting, pageSetup, 0}},
+ {2525, {wxHtmlEasyPrinting, setFonts, 3}},
+ {2526, {wxHtmlEasyPrinting, setHeader, 2}},
+ {2527, {wxHtmlEasyPrinting, setFooter, 2}},
+ {2529, {wxGLCanvas, new_2, 2}},
+ {2530, {wxGLCanvas, new_3_1, 3}},
+ {2531, {wxGLCanvas, new_3_0, 3}},
+ {2532, {wxGLCanvas, getContext, 0}},
+ {2534, {wxGLCanvas, setCurrent, 0}},
+ {2535, {wxGLCanvas, swapBuffers, 0}},
+ {2536, {wxGLCanvas, 'Destroy', undefined}},
+ {2537, {wxAuiManager, new, 1}},
+ {2538, {wxAuiManager, destruct, 0}},
+ {2539, {wxAuiManager, addPane_2_1, 2}},
+ {2540, {wxAuiManager, addPane_3, 3}},
+ {2541, {wxAuiManager, addPane_2_0, 2}},
+ {2542, {wxAuiManager, detachPane, 1}},
+ {2543, {wxAuiManager, getAllPanes, 0}},
+ {2544, {wxAuiManager, getArtProvider, 0}},
+ {2545, {wxAuiManager, getDockSizeConstraint, 2}},
+ {2546, {wxAuiManager, getFlags, 0}},
+ {2547, {wxAuiManager, getManagedWindow, 0}},
+ {2548, {wxAuiManager, getManager, 1}},
+ {2549, {wxAuiManager, getPane_1_1, 1}},
+ {2550, {wxAuiManager, getPane_1_0, 1}},
+ {2551, {wxAuiManager, hideHint, 0}},
+ {2552, {wxAuiManager, insertPane, 3}},
+ {2553, {wxAuiManager, loadPaneInfo, 2}},
+ {2554, {wxAuiManager, loadPerspective, 2}},
+ {2555, {wxAuiManager, savePaneInfo, 1}},
+ {2556, {wxAuiManager, savePerspective, 0}},
+ {2557, {wxAuiManager, setArtProvider, 1}},
+ {2558, {wxAuiManager, setDockSizeConstraint, 2}},
+ {2559, {wxAuiManager, setFlags, 1}},
+ {2560, {wxAuiManager, setManagedWindow, 1}},
+ {2561, {wxAuiManager, showHint, 1}},
+ {2562, {wxAuiManager, unInit, 0}},
+ {2563, {wxAuiManager, update, 0}},
+ {2564, {wxAuiPaneInfo, new_0, 0}},
+ {2565, {wxAuiPaneInfo, new_1, 1}},
+ {2566, {wxAuiPaneInfo, destruct, 0}},
+ {2567, {wxAuiPaneInfo, bestSize_1, 1}},
+ {2568, {wxAuiPaneInfo, bestSize_2, 2}},
+ {2569, {wxAuiPaneInfo, bottom, 0}},
+ {2570, {wxAuiPaneInfo, bottomDockable, 1}},
+ {2571, {wxAuiPaneInfo, caption, 1}},
+ {2572, {wxAuiPaneInfo, captionVisible, 1}},
+ {2573, {wxAuiPaneInfo, centre, 0}},
+ {2574, {wxAuiPaneInfo, centrePane, 0}},
+ {2575, {wxAuiPaneInfo, closeButton, 1}},
+ {2576, {wxAuiPaneInfo, defaultPane, 0}},
+ {2577, {wxAuiPaneInfo, destroyOnClose, 1}},
+ {2578, {wxAuiPaneInfo, direction, 1}},
+ {2579, {wxAuiPaneInfo, dock, 0}},
+ {2580, {wxAuiPaneInfo, dockable, 1}},
+ {2581, {wxAuiPaneInfo, fixed, 0}},
+ {2582, {wxAuiPaneInfo, float, 0}},
+ {2583, {wxAuiPaneInfo, floatable, 1}},
+ {2584, {wxAuiPaneInfo, floatingPosition_1, 1}},
+ {2585, {wxAuiPaneInfo, floatingPosition_2, 2}},
+ {2586, {wxAuiPaneInfo, floatingSize_1, 1}},
+ {2587, {wxAuiPaneInfo, floatingSize_2, 2}},
+ {2588, {wxAuiPaneInfo, gripper, 1}},
+ {2589, {wxAuiPaneInfo, gripperTop, 1}},
+ {2590, {wxAuiPaneInfo, hasBorder, 0}},
+ {2591, {wxAuiPaneInfo, hasCaption, 0}},
+ {2592, {wxAuiPaneInfo, hasCloseButton, 0}},
+ {2593, {wxAuiPaneInfo, hasFlag, 1}},
+ {2594, {wxAuiPaneInfo, hasGripper, 0}},
+ {2595, {wxAuiPaneInfo, hasGripperTop, 0}},
+ {2596, {wxAuiPaneInfo, hasMaximizeButton, 0}},
+ {2597, {wxAuiPaneInfo, hasMinimizeButton, 0}},
+ {2598, {wxAuiPaneInfo, hasPinButton, 0}},
+ {2599, {wxAuiPaneInfo, hide, 0}},
+ {2600, {wxAuiPaneInfo, isBottomDockable, 0}},
+ {2601, {wxAuiPaneInfo, isDocked, 0}},
+ {2602, {wxAuiPaneInfo, isFixed, 0}},
+ {2603, {wxAuiPaneInfo, isFloatable, 0}},
+ {2604, {wxAuiPaneInfo, isFloating, 0}},
+ {2605, {wxAuiPaneInfo, isLeftDockable, 0}},
+ {2606, {wxAuiPaneInfo, isMovable, 0}},
+ {2607, {wxAuiPaneInfo, isOk, 0}},
+ {2608, {wxAuiPaneInfo, isResizable, 0}},
+ {2609, {wxAuiPaneInfo, isRightDockable, 0}},
+ {2610, {wxAuiPaneInfo, isShown, 0}},
+ {2611, {wxAuiPaneInfo, isToolbar, 0}},
+ {2612, {wxAuiPaneInfo, isTopDockable, 0}},
+ {2613, {wxAuiPaneInfo, layer, 1}},
+ {2614, {wxAuiPaneInfo, left, 0}},
+ {2615, {wxAuiPaneInfo, leftDockable, 1}},
+ {2616, {wxAuiPaneInfo, maxSize_1, 1}},
+ {2617, {wxAuiPaneInfo, maxSize_2, 2}},
+ {2618, {wxAuiPaneInfo, maximizeButton, 1}},
+ {2619, {wxAuiPaneInfo, minSize_1, 1}},
+ {2620, {wxAuiPaneInfo, minSize_2, 2}},
+ {2621, {wxAuiPaneInfo, minimizeButton, 1}},
+ {2622, {wxAuiPaneInfo, movable, 1}},
+ {2623, {wxAuiPaneInfo, name, 1}},
+ {2624, {wxAuiPaneInfo, paneBorder, 1}},
+ {2625, {wxAuiPaneInfo, pinButton, 1}},
+ {2626, {wxAuiPaneInfo, position, 1}},
+ {2627, {wxAuiPaneInfo, resizable, 1}},
+ {2628, {wxAuiPaneInfo, right, 0}},
+ {2629, {wxAuiPaneInfo, rightDockable, 1}},
+ {2630, {wxAuiPaneInfo, row, 1}},
+ {2631, {wxAuiPaneInfo, safeSet, 1}},
+ {2632, {wxAuiPaneInfo, setFlag, 2}},
+ {2633, {wxAuiPaneInfo, show, 1}},
+ {2634, {wxAuiPaneInfo, toolbarPane, 0}},
+ {2635, {wxAuiPaneInfo, top, 0}},
+ {2636, {wxAuiPaneInfo, topDockable, 1}},
+ {2637, {wxAuiPaneInfo, window, 1}},
+ {2638, {wxAuiNotebook, new_0, 0}},
+ {2639, {wxAuiNotebook, new_2, 2}},
+ {2640, {wxAuiNotebook, addPage, 3}},
+ {2641, {wxAuiNotebook, create, 2}},
+ {2642, {wxAuiNotebook, deletePage, 1}},
+ {2643, {wxAuiNotebook, getArtProvider, 0}},
+ {2644, {wxAuiNotebook, getPage, 1}},
+ {2645, {wxAuiNotebook, getPageBitmap, 1}},
+ {2646, {wxAuiNotebook, getPageCount, 0}},
+ {2647, {wxAuiNotebook, getPageIndex, 1}},
+ {2648, {wxAuiNotebook, getPageText, 1}},
+ {2649, {wxAuiNotebook, getSelection, 0}},
+ {2650, {wxAuiNotebook, insertPage, 4}},
+ {2651, {wxAuiNotebook, removePage, 1}},
+ {2652, {wxAuiNotebook, setArtProvider, 1}},
+ {2653, {wxAuiNotebook, setFont, 1}},
+ {2654, {wxAuiNotebook, setPageBitmap, 2}},
+ {2655, {wxAuiNotebook, setPageText, 2}},
+ {2656, {wxAuiNotebook, setSelection, 1}},
+ {2657, {wxAuiNotebook, setTabCtrlHeight, 1}},
+ {2658, {wxAuiNotebook, setUniformBitmapSize, 1}},
+ {2659, {wxAuiNotebook, 'Destroy', undefined}},
+ {2660, {wxMDIParentFrame, new_0, 0}},
+ {2661, {wxMDIParentFrame, new_4, 4}},
+ {2662, {wxMDIParentFrame, destruct, 0}},
+ {2663, {wxMDIParentFrame, activateNext, 0}},
+ {2664, {wxMDIParentFrame, activatePrevious, 0}},
+ {2665, {wxMDIParentFrame, arrangeIcons, 0}},
+ {2666, {wxMDIParentFrame, cascade, 0}},
+ {2667, {wxMDIParentFrame, create, 4}},
+ {2668, {wxMDIParentFrame, getActiveChild, 0}},
+ {2669, {wxMDIParentFrame, getClientWindow, 0}},
+ {2670, {wxMDIParentFrame, tile, 1}},
+ {2671, {wxMDIChildFrame, new_0, 0}},
+ {2672, {wxMDIChildFrame, new_4, 4}},
+ {2673, {wxMDIChildFrame, destruct, 0}},
+ {2674, {wxMDIChildFrame, activate, 0}},
+ {2675, {wxMDIChildFrame, create, 4}},
+ {2676, {wxMDIChildFrame, maximize, 1}},
+ {2677, {wxMDIChildFrame, restore, 0}},
+ {2678, {wxMDIClientWindow, new_0, 0}},
+ {2679, {wxMDIClientWindow, new_2, 2}},
+ {2680, {wxMDIClientWindow, destruct, 0}},
+ {2681, {wxMDIClientWindow, createClient, 2}},
+ {2682, {wxLayoutAlgorithm, new, 0}},
+ {2683, {wxLayoutAlgorithm, layoutFrame, 2}},
+ {2684, {wxLayoutAlgorithm, layoutMDIFrame, 2}},
+ {2685, {wxLayoutAlgorithm, layoutWindow, 2}},
+ {2686, {wxLayoutAlgorithm, 'Destroy', undefined}},
+ {2687, {wxEvent, getId, 0}},
+ {2688, {wxEvent, getSkipped, 0}},
+ {2689, {wxEvent, getTimestamp, 0}},
+ {2690, {wxEvent, isCommandEvent, 0}},
+ {2691, {wxEvent, resumePropagation, 1}},
+ {2692, {wxEvent, shouldPropagate, 0}},
+ {2693, {wxEvent, skip, 1}},
+ {2694, {wxEvent, stopPropagation, 0}},
+ {2695, {wxCommandEvent, getClientData, 0}},
+ {2696, {wxCommandEvent, getExtraLong, 0}},
+ {2697, {wxCommandEvent, getInt, 0}},
+ {2698, {wxCommandEvent, getSelection, 0}},
+ {2699, {wxCommandEvent, getString, 0}},
+ {2700, {wxCommandEvent, isChecked, 0}},
+ {2701, {wxCommandEvent, isSelection, 0}},
+ {2702, {wxCommandEvent, setInt, 1}},
+ {2703, {wxCommandEvent, setString, 1}},
+ {2704, {wxScrollEvent, getOrientation, 0}},
+ {2705, {wxScrollEvent, getPosition, 0}},
+ {2706, {wxScrollWinEvent, getOrientation, 0}},
+ {2707, {wxScrollWinEvent, getPosition, 0}},
+ {2708, {wxMouseEvent, altDown, 0}},
+ {2709, {wxMouseEvent, button, 1}},
+ {2710, {wxMouseEvent, buttonDClick, 1}},
+ {2711, {wxMouseEvent, buttonDown, 1}},
+ {2712, {wxMouseEvent, buttonUp, 1}},
+ {2713, {wxMouseEvent, cmdDown, 0}},
+ {2714, {wxMouseEvent, controlDown, 0}},
+ {2715, {wxMouseEvent, dragging, 0}},
+ {2716, {wxMouseEvent, entering, 0}},
+ {2717, {wxMouseEvent, getButton, 0}},
+ {2720, {wxMouseEvent, getPosition, 0}},
+ {2721, {wxMouseEvent, getLogicalPosition, 1}},
+ {2722, {wxMouseEvent, getLinesPerAction, 0}},
+ {2723, {wxMouseEvent, getWheelRotation, 0}},
+ {2724, {wxMouseEvent, getWheelDelta, 0}},
+ {2725, {wxMouseEvent, getX, 0}},
+ {2726, {wxMouseEvent, getY, 0}},
+ {2727, {wxMouseEvent, isButton, 0}},
+ {2728, {wxMouseEvent, isPageScroll, 0}},
+ {2729, {wxMouseEvent, leaving, 0}},
+ {2730, {wxMouseEvent, leftDClick, 0}},
+ {2731, {wxMouseEvent, leftDown, 0}},
+ {2732, {wxMouseEvent, leftIsDown, 0}},
+ {2733, {wxMouseEvent, leftUp, 0}},
+ {2734, {wxMouseEvent, metaDown, 0}},
+ {2735, {wxMouseEvent, middleDClick, 0}},
+ {2736, {wxMouseEvent, middleDown, 0}},
+ {2737, {wxMouseEvent, middleIsDown, 0}},
+ {2738, {wxMouseEvent, middleUp, 0}},
+ {2739, {wxMouseEvent, moving, 0}},
+ {2740, {wxMouseEvent, rightDClick, 0}},
+ {2741, {wxMouseEvent, rightDown, 0}},
+ {2742, {wxMouseEvent, rightIsDown, 0}},
+ {2743, {wxMouseEvent, rightUp, 0}},
+ {2744, {wxMouseEvent, shiftDown, 0}},
+ {2745, {wxSetCursorEvent, getCursor, 0}},
+ {2746, {wxSetCursorEvent, getX, 0}},
+ {2747, {wxSetCursorEvent, getY, 0}},
+ {2748, {wxSetCursorEvent, hasCursor, 0}},
+ {2749, {wxSetCursorEvent, setCursor, 1}},
+ {2750, {wxKeyEvent, altDown, 0}},
+ {2751, {wxKeyEvent, cmdDown, 0}},
+ {2752, {wxKeyEvent, controlDown, 0}},
+ {2753, {wxKeyEvent, getKeyCode, 0}},
+ {2754, {wxKeyEvent, getModifiers, 0}},
+ {2757, {wxKeyEvent, getPosition, 0}},
+ {2758, {wxKeyEvent, getRawKeyCode, 0}},
+ {2759, {wxKeyEvent, getRawKeyFlags, 0}},
+ {2760, {wxKeyEvent, getUnicodeKey, 0}},
+ {2761, {wxKeyEvent, getX, 0}},
+ {2762, {wxKeyEvent, getY, 0}},
+ {2763, {wxKeyEvent, hasModifiers, 0}},
+ {2764, {wxKeyEvent, metaDown, 0}},
+ {2765, {wxKeyEvent, shiftDown, 0}},
+ {2766, {wxSizeEvent, getSize, 0}},
+ {2767, {wxMoveEvent, getPosition, 0}},
+ {2768, {wxEraseEvent, getDC, 0}},
+ {2769, {wxFocusEvent, getWindow, 0}},
+ {2770, {wxChildFocusEvent, getWindow, 0}},
+ {2771, {wxMenuEvent, getMenu, 0}},
+ {2772, {wxMenuEvent, getMenuId, 0}},
+ {2773, {wxMenuEvent, isPopup, 0}},
+ {2774, {wxCloseEvent, canVeto, 0}},
+ {2775, {wxCloseEvent, getLoggingOff, 0}},
+ {2776, {wxCloseEvent, setCanVeto, 1}},
+ {2777, {wxCloseEvent, setLoggingOff, 1}},
+ {2778, {wxCloseEvent, veto, 1}},
+ {2779, {wxShowEvent, setShow, 1}},
+ {2780, {wxShowEvent, getShow, 0}},
+ {2781, {wxIconizeEvent, iconized, 0}},
+ {2782, {wxJoystickEvent, buttonDown, 1}},
+ {2783, {wxJoystickEvent, buttonIsDown, 1}},
+ {2784, {wxJoystickEvent, buttonUp, 1}},
+ {2785, {wxJoystickEvent, getButtonChange, 0}},
+ {2786, {wxJoystickEvent, getButtonState, 0}},
+ {2787, {wxJoystickEvent, getJoystick, 0}},
+ {2788, {wxJoystickEvent, getPosition, 0}},
+ {2789, {wxJoystickEvent, getZPosition, 0}},
+ {2790, {wxJoystickEvent, isButton, 0}},
+ {2791, {wxJoystickEvent, isMove, 0}},
+ {2792, {wxJoystickEvent, isZMove, 0}},
+ {2793, {wxUpdateUIEvent, canUpdate, 1}},
+ {2794, {wxUpdateUIEvent, check, 1}},
+ {2795, {wxUpdateUIEvent, enable, 1}},
+ {2796, {wxUpdateUIEvent, show, 1}},
+ {2797, {wxUpdateUIEvent, getChecked, 0}},
+ {2798, {wxUpdateUIEvent, getEnabled, 0}},
+ {2799, {wxUpdateUIEvent, getShown, 0}},
+ {2800, {wxUpdateUIEvent, getSetChecked, 0}},
+ {2801, {wxUpdateUIEvent, getSetEnabled, 0}},
+ {2802, {wxUpdateUIEvent, getSetShown, 0}},
+ {2803, {wxUpdateUIEvent, getSetText, 0}},
+ {2804, {wxUpdateUIEvent, getText, 0}},
+ {2805, {wxUpdateUIEvent, getMode, 0}},
+ {2806, {wxUpdateUIEvent, getUpdateInterval, 0}},
+ {2807, {wxUpdateUIEvent, resetUpdateTime, 0}},
+ {2808, {wxUpdateUIEvent, setMode, 1}},
+ {2809, {wxUpdateUIEvent, setText, 1}},
+ {2810, {wxUpdateUIEvent, setUpdateInterval, 1}},
+ {2811, {wxMouseCaptureChangedEvent, getCapturedWindow, 0}},
+ {2812, {wxPaletteChangedEvent, setChangedWindow, 1}},
+ {2813, {wxPaletteChangedEvent, getChangedWindow, 0}},
+ {2814, {wxQueryNewPaletteEvent, setPaletteRealized, 1}},
+ {2815, {wxQueryNewPaletteEvent, getPaletteRealized, 0}},
+ {2816, {wxNavigationKeyEvent, getDirection, 0}},
+ {2817, {wxNavigationKeyEvent, setDirection, 1}},
+ {2818, {wxNavigationKeyEvent, isWindowChange, 0}},
+ {2819, {wxNavigationKeyEvent, setWindowChange, 1}},
+ {2820, {wxNavigationKeyEvent, isFromTab, 0}},
+ {2821, {wxNavigationKeyEvent, setFromTab, 1}},
+ {2822, {wxNavigationKeyEvent, getCurrentFocus, 0}},
+ {2823, {wxNavigationKeyEvent, setCurrentFocus, 1}},
+ {2824, {wxHelpEvent, getOrigin, 0}},
+ {2825, {wxHelpEvent, getPosition, 0}},
+ {2826, {wxHelpEvent, setOrigin, 1}},
+ {2827, {wxHelpEvent, setPosition, 1}},
+ {2828, {wxContextMenuEvent, getPosition, 0}},
+ {2829, {wxContextMenuEvent, setPosition, 1}},
+ {2830, {wxIdleEvent, canSend, 1}},
+ {2831, {wxIdleEvent, getMode, 0}},
+ {2832, {wxIdleEvent, requestMore, 1}},
+ {2833, {wxIdleEvent, moreRequested, 0}},
+ {2834, {wxIdleEvent, setMode, 1}},
+ {2835, {wxGridEvent, altDown, 0}},
+ {2836, {wxGridEvent, controlDown, 0}},
+ {2837, {wxGridEvent, getCol, 0}},
+ {2838, {wxGridEvent, getPosition, 0}},
+ {2839, {wxGridEvent, getRow, 0}},
+ {2840, {wxGridEvent, metaDown, 0}},
+ {2841, {wxGridEvent, selecting, 0}},
+ {2842, {wxGridEvent, shiftDown, 0}},
+ {2843, {wxNotifyEvent, allow, 0}},
+ {2844, {wxNotifyEvent, isAllowed, 0}},
+ {2845, {wxNotifyEvent, veto, 0}},
+ {2846, {wxSashEvent, getEdge, 0}},
+ {2847, {wxSashEvent, getDragRect, 0}},
+ {2848, {wxSashEvent, getDragStatus, 0}},
+ {2849, {wxListEvent, getCacheFrom, 0}},
+ {2850, {wxListEvent, getCacheTo, 0}},
+ {2851, {wxListEvent, getKeyCode, 0}},
+ {2852, {wxListEvent, getIndex, 0}},
+ {2853, {wxListEvent, getColumn, 0}},
+ {2854, {wxListEvent, getPoint, 0}},
+ {2855, {wxListEvent, getLabel, 0}},
+ {2856, {wxListEvent, getText, 0}},
+ {2857, {wxListEvent, getImage, 0}},
+ {2858, {wxListEvent, getData, 0}},
+ {2859, {wxListEvent, getMask, 0}},
+ {2860, {wxListEvent, getItem, 0}},
+ {2861, {wxListEvent, isEditCancelled, 0}},
+ {2862, {wxDateEvent, getDate, 0}},
+ {2863, {wxCalendarEvent, getWeekDay, 0}},
+ {2864, {wxFileDirPickerEvent, getPath, 0}},
+ {2865, {wxColourPickerEvent, getColour, 0}},
+ {2866, {wxFontPickerEvent, getFont, 0}},
+ {2867, {wxStyledTextEvent, getPosition, 0}},
+ {2868, {wxStyledTextEvent, getKey, 0}},
+ {2869, {wxStyledTextEvent, getModifiers, 0}},
+ {2870, {wxStyledTextEvent, getModificationType, 0}},
+ {2871, {wxStyledTextEvent, getText, 0}},
+ {2872, {wxStyledTextEvent, getLength, 0}},
+ {2873, {wxStyledTextEvent, getLinesAdded, 0}},
+ {2874, {wxStyledTextEvent, getLine, 0}},
+ {2875, {wxStyledTextEvent, getFoldLevelNow, 0}},
+ {2876, {wxStyledTextEvent, getFoldLevelPrev, 0}},
+ {2877, {wxStyledTextEvent, getMargin, 0}},
+ {2878, {wxStyledTextEvent, getMessage, 0}},
+ {2879, {wxStyledTextEvent, getWParam, 0}},
+ {2880, {wxStyledTextEvent, getLParam, 0}},
+ {2881, {wxStyledTextEvent, getListType, 0}},
+ {2882, {wxStyledTextEvent, getX, 0}},
+ {2883, {wxStyledTextEvent, getY, 0}},
+ {2884, {wxStyledTextEvent, getDragText, 0}},
+ {2885, {wxStyledTextEvent, getDragAllowMove, 0}},
+ {2886, {wxStyledTextEvent, getDragResult, 0}},
+ {2887, {wxStyledTextEvent, getShift, 0}},
+ {2888, {wxStyledTextEvent, getControl, 0}},
+ {2889, {wxStyledTextEvent, getAlt, 0}},
+ {2890, {utils, getKeyState, 1}},
+ {2891, {utils, getMousePosition, 2}},
+ {2892, {utils, getMouseState, 0}},
+ {2893, {utils, setDetectableAutoRepeat, 1}},
+ {2894, {utils, bell, 0}},
+ {2895, {utils, findMenuItemId, 3}},
+ {2896, {utils, genericFindWindowAtPoint, 1}},
+ {2897, {utils, findWindowAtPoint, 1}},
+ {2898, {utils, beginBusyCursor, 1}},
+ {2899, {utils, endBusyCursor, 0}},
+ {2900, {utils, isBusy, 0}},
+ {2901, {utils, shutdown, 1}},
+ {2902, {utils, shell, 1}},
+ {2903, {utils, launchDefaultBrowser, 2}},
+ {2904, {utils, getEmailAddress, 0}},
+ {2905, {utils, getUserId, 0}},
+ {2906, {utils, getHomeDir, 0}},
+ {2907, {utils, newId, 0}},
+ {2908, {utils, registerId, 1}},
+ {2909, {utils, getCurrentId, 0}},
+ {2910, {utils, getOsDescription, 0}},
+ {2911, {utils, isPlatformLittleEndian, 0}},
+ {2912, {utils, isPlatform64Bit, 0}},
+ {2913, {wxPrintout, new, 1}},
+ {2914, {wxPrintout, destruct, 0}},
+ {2915, {wxPrintout, getDC, 0}},
+ {2916, {wxPrintout, getPageSizeMM, 2}},
+ {2917, {wxPrintout, getPageSizePixels, 2}},
+ {2918, {wxPrintout, getPaperRectPixels, 0}},
+ {2919, {wxPrintout, getPPIPrinter, 2}},
+ {2920, {wxPrintout, getPPIScreen, 2}},
+ {2921, {wxPrintout, getTitle, 0}},
+ {2922, {wxPrintout, isPreview, 0}},
+ {2923, {wxPrintout, fitThisSizeToPaper, 1}},
+ {2924, {wxPrintout, fitThisSizeToPage, 1}},
+ {2925, {wxPrintout, fitThisSizeToPageMargins, 2}},
+ {2926, {wxPrintout, mapScreenSizeToPaper, 0}},
+ {2927, {wxPrintout, mapScreenSizeToPage, 0}},
+ {2928, {wxPrintout, mapScreenSizeToPageMargins, 1}},
+ {2929, {wxPrintout, mapScreenSizeToDevice, 0}},
+ {2930, {wxPrintout, getLogicalPaperRect, 0}},
+ {2931, {wxPrintout, getLogicalPageRect, 0}},
+ {2932, {wxPrintout, getLogicalPageMarginsRect, 1}},
+ {2933, {wxPrintout, setLogicalOrigin, 2}},
+ {2934, {wxPrintout, offsetLogicalOrigin, 2}},
+ {2935, {wxStyledTextCtrl, new_2, 2}},
+ {2936, {wxStyledTextCtrl, new_0, 0}},
+ {2937, {wxStyledTextCtrl, destruct, 0}},
+ {2938, {wxStyledTextCtrl, create, 2}},
+ {2939, {wxStyledTextCtrl, addText, 1}},
+ {2940, {wxStyledTextCtrl, addStyledText, 1}},
+ {2941, {wxStyledTextCtrl, insertText, 2}},
+ {2942, {wxStyledTextCtrl, clearAll, 0}},
+ {2943, {wxStyledTextCtrl, clearDocumentStyle, 0}},
+ {2944, {wxStyledTextCtrl, getLength, 0}},
+ {2945, {wxStyledTextCtrl, getCharAt, 1}},
+ {2946, {wxStyledTextCtrl, getCurrentPos, 0}},
+ {2947, {wxStyledTextCtrl, getAnchor, 0}},
+ {2948, {wxStyledTextCtrl, getStyleAt, 1}},
+ {2949, {wxStyledTextCtrl, redo, 0}},
+ {2950, {wxStyledTextCtrl, setUndoCollection, 1}},
+ {2951, {wxStyledTextCtrl, selectAll, 0}},
+ {2952, {wxStyledTextCtrl, setSavePoint, 0}},
+ {2953, {wxStyledTextCtrl, getStyledText, 2}},
+ {2954, {wxStyledTextCtrl, canRedo, 0}},
+ {2955, {wxStyledTextCtrl, markerLineFromHandle, 1}},
+ {2956, {wxStyledTextCtrl, markerDeleteHandle, 1}},
+ {2957, {wxStyledTextCtrl, getUndoCollection, 0}},
+ {2958, {wxStyledTextCtrl, getViewWhiteSpace, 0}},
+ {2959, {wxStyledTextCtrl, setViewWhiteSpace, 1}},
+ {2960, {wxStyledTextCtrl, positionFromPoint, 1}},
+ {2961, {wxStyledTextCtrl, positionFromPointClose, 2}},
+ {2962, {wxStyledTextCtrl, gotoLine, 1}},
+ {2963, {wxStyledTextCtrl, gotoPos, 1}},
+ {2964, {wxStyledTextCtrl, setAnchor, 1}},
+ {2965, {wxStyledTextCtrl, getCurLine, 1}},
+ {2966, {wxStyledTextCtrl, getEndStyled, 0}},
+ {2967, {wxStyledTextCtrl, convertEOLs, 1}},
+ {2968, {wxStyledTextCtrl, getEOLMode, 0}},
+ {2969, {wxStyledTextCtrl, setEOLMode, 1}},
+ {2970, {wxStyledTextCtrl, startStyling, 2}},
+ {2971, {wxStyledTextCtrl, setStyling, 2}},
+ {2972, {wxStyledTextCtrl, getBufferedDraw, 0}},
+ {2973, {wxStyledTextCtrl, setBufferedDraw, 1}},
+ {2974, {wxStyledTextCtrl, setTabWidth, 1}},
+ {2975, {wxStyledTextCtrl, getTabWidth, 0}},
+ {2976, {wxStyledTextCtrl, setCodePage, 1}},
+ {2977, {wxStyledTextCtrl, markerDefine, 3}},
+ {2978, {wxStyledTextCtrl, markerSetForeground, 2}},
+ {2979, {wxStyledTextCtrl, markerSetBackground, 2}},
+ {2980, {wxStyledTextCtrl, markerAdd, 2}},
+ {2981, {wxStyledTextCtrl, markerDelete, 2}},
+ {2982, {wxStyledTextCtrl, markerDeleteAll, 1}},
+ {2983, {wxStyledTextCtrl, markerGet, 1}},
+ {2984, {wxStyledTextCtrl, markerNext, 2}},
+ {2985, {wxStyledTextCtrl, markerPrevious, 2}},
+ {2986, {wxStyledTextCtrl, markerDefineBitmap, 2}},
+ {2987, {wxStyledTextCtrl, markerAddSet, 2}},
+ {2988, {wxStyledTextCtrl, markerSetAlpha, 2}},
+ {2989, {wxStyledTextCtrl, setMarginType, 2}},
+ {2990, {wxStyledTextCtrl, getMarginType, 1}},
+ {2991, {wxStyledTextCtrl, setMarginWidth, 2}},
+ {2992, {wxStyledTextCtrl, getMarginWidth, 1}},
+ {2993, {wxStyledTextCtrl, setMarginMask, 2}},
+ {2994, {wxStyledTextCtrl, getMarginMask, 1}},
+ {2995, {wxStyledTextCtrl, setMarginSensitive, 2}},
+ {2996, {wxStyledTextCtrl, getMarginSensitive, 1}},
+ {2997, {wxStyledTextCtrl, styleClearAll, 0}},
+ {2998, {wxStyledTextCtrl, styleSetForeground, 2}},
+ {2999, {wxStyledTextCtrl, styleSetBackground, 2}},
+ {3000, {wxStyledTextCtrl, styleSetBold, 2}},
+ {3001, {wxStyledTextCtrl, styleSetItalic, 2}},
+ {3002, {wxStyledTextCtrl, styleSetSize, 2}},
+ {3003, {wxStyledTextCtrl, styleSetFaceName, 2}},
+ {3004, {wxStyledTextCtrl, styleSetEOLFilled, 2}},
+ {3005, {wxStyledTextCtrl, styleResetDefault, 0}},
+ {3006, {wxStyledTextCtrl, styleSetUnderline, 2}},
+ {3007, {wxStyledTextCtrl, styleSetCase, 2}},
+ {3008, {wxStyledTextCtrl, styleSetHotSpot, 2}},
+ {3009, {wxStyledTextCtrl, setSelForeground, 2}},
+ {3010, {wxStyledTextCtrl, setSelBackground, 2}},
+ {3011, {wxStyledTextCtrl, getSelAlpha, 0}},
+ {3012, {wxStyledTextCtrl, setSelAlpha, 1}},
+ {3013, {wxStyledTextCtrl, setCaretForeground, 1}},
+ {3014, {wxStyledTextCtrl, cmdKeyAssign, 3}},
+ {3015, {wxStyledTextCtrl, cmdKeyClear, 2}},
+ {3016, {wxStyledTextCtrl, cmdKeyClearAll, 0}},
+ {3017, {wxStyledTextCtrl, setStyleBytes, 2}},
+ {3018, {wxStyledTextCtrl, styleSetVisible, 2}},
+ {3019, {wxStyledTextCtrl, getCaretPeriod, 0}},
+ {3020, {wxStyledTextCtrl, setCaretPeriod, 1}},
+ {3021, {wxStyledTextCtrl, setWordChars, 1}},
+ {3022, {wxStyledTextCtrl, beginUndoAction, 0}},
+ {3023, {wxStyledTextCtrl, endUndoAction, 0}},
+ {3024, {wxStyledTextCtrl, indicatorSetStyle, 2}},
+ {3025, {wxStyledTextCtrl, indicatorGetStyle, 1}},
+ {3026, {wxStyledTextCtrl, indicatorSetForeground, 2}},
+ {3027, {wxStyledTextCtrl, indicatorGetForeground, 1}},
+ {3028, {wxStyledTextCtrl, setWhitespaceForeground, 2}},
+ {3029, {wxStyledTextCtrl, setWhitespaceBackground, 2}},
+ {3030, {wxStyledTextCtrl, getStyleBits, 0}},
+ {3031, {wxStyledTextCtrl, setLineState, 2}},
+ {3032, {wxStyledTextCtrl, getLineState, 1}},
+ {3033, {wxStyledTextCtrl, getMaxLineState, 0}},
+ {3034, {wxStyledTextCtrl, getCaretLineVisible, 0}},
+ {3035, {wxStyledTextCtrl, setCaretLineVisible, 1}},
+ {3036, {wxStyledTextCtrl, getCaretLineBackground, 0}},
+ {3037, {wxStyledTextCtrl, setCaretLineBackground, 1}},
+ {3038, {wxStyledTextCtrl, autoCompShow, 2}},
+ {3039, {wxStyledTextCtrl, autoCompCancel, 0}},
+ {3040, {wxStyledTextCtrl, autoCompActive, 0}},
+ {3041, {wxStyledTextCtrl, autoCompPosStart, 0}},
+ {3042, {wxStyledTextCtrl, autoCompComplete, 0}},
+ {3043, {wxStyledTextCtrl, autoCompStops, 1}},
+ {3044, {wxStyledTextCtrl, autoCompSetSeparator, 1}},
+ {3045, {wxStyledTextCtrl, autoCompGetSeparator, 0}},
+ {3046, {wxStyledTextCtrl, autoCompSelect, 1}},
+ {3047, {wxStyledTextCtrl, autoCompSetCancelAtStart, 1}},
+ {3048, {wxStyledTextCtrl, autoCompGetCancelAtStart, 0}},
+ {3049, {wxStyledTextCtrl, autoCompSetFillUps, 1}},
+ {3050, {wxStyledTextCtrl, autoCompSetChooseSingle, 1}},
+ {3051, {wxStyledTextCtrl, autoCompGetChooseSingle, 0}},
+ {3052, {wxStyledTextCtrl, autoCompSetIgnoreCase, 1}},
+ {3053, {wxStyledTextCtrl, autoCompGetIgnoreCase, 0}},
+ {3054, {wxStyledTextCtrl, userListShow, 2}},
+ {3055, {wxStyledTextCtrl, autoCompSetAutoHide, 1}},
+ {3056, {wxStyledTextCtrl, autoCompGetAutoHide, 0}},
+ {3057, {wxStyledTextCtrl, autoCompSetDropRestOfWord, 1}},
+ {3058, {wxStyledTextCtrl, autoCompGetDropRestOfWord, 0}},
+ {3059, {wxStyledTextCtrl, registerImage, 2}},
+ {3060, {wxStyledTextCtrl, clearRegisteredImages, 0}},
+ {3061, {wxStyledTextCtrl, autoCompGetTypeSeparator, 0}},
+ {3062, {wxStyledTextCtrl, autoCompSetTypeSeparator, 1}},
+ {3063, {wxStyledTextCtrl, autoCompSetMaxWidth, 1}},
+ {3064, {wxStyledTextCtrl, autoCompGetMaxWidth, 0}},
+ {3065, {wxStyledTextCtrl, autoCompSetMaxHeight, 1}},
+ {3066, {wxStyledTextCtrl, autoCompGetMaxHeight, 0}},
+ {3067, {wxStyledTextCtrl, setIndent, 1}},
+ {3068, {wxStyledTextCtrl, getIndent, 0}},
+ {3069, {wxStyledTextCtrl, setUseTabs, 1}},
+ {3070, {wxStyledTextCtrl, getUseTabs, 0}},
+ {3071, {wxStyledTextCtrl, setLineIndentation, 2}},
+ {3072, {wxStyledTextCtrl, getLineIndentation, 1}},
+ {3073, {wxStyledTextCtrl, getLineIndentPosition, 1}},
+ {3074, {wxStyledTextCtrl, getColumn, 1}},
+ {3075, {wxStyledTextCtrl, setUseHorizontalScrollBar, 1}},
+ {3076, {wxStyledTextCtrl, getUseHorizontalScrollBar, 0}},
+ {3077, {wxStyledTextCtrl, setIndentationGuides, 1}},
+ {3078, {wxStyledTextCtrl, getIndentationGuides, 0}},
+ {3079, {wxStyledTextCtrl, setHighlightGuide, 1}},
+ {3080, {wxStyledTextCtrl, getHighlightGuide, 0}},
+ {3081, {wxStyledTextCtrl, getLineEndPosition, 1}},
+ {3082, {wxStyledTextCtrl, getCodePage, 0}},
+ {3083, {wxStyledTextCtrl, getCaretForeground, 0}},
+ {3084, {wxStyledTextCtrl, getReadOnly, 0}},
+ {3085, {wxStyledTextCtrl, setCurrentPos, 1}},
+ {3086, {wxStyledTextCtrl, setSelectionStart, 1}},
+ {3087, {wxStyledTextCtrl, getSelectionStart, 0}},
+ {3088, {wxStyledTextCtrl, setSelectionEnd, 1}},
+ {3089, {wxStyledTextCtrl, getSelectionEnd, 0}},
+ {3090, {wxStyledTextCtrl, setPrintMagnification, 1}},
+ {3091, {wxStyledTextCtrl, getPrintMagnification, 0}},
+ {3092, {wxStyledTextCtrl, setPrintColourMode, 1}},
+ {3093, {wxStyledTextCtrl, getPrintColourMode, 0}},
+ {3094, {wxStyledTextCtrl, findText, 4}},
+ {3095, {wxStyledTextCtrl, formatRange, 7}},
+ {3096, {wxStyledTextCtrl, getFirstVisibleLine, 0}},
+ {3097, {wxStyledTextCtrl, getLine, 1}},
+ {3098, {wxStyledTextCtrl, getLineCount, 0}},
+ {3099, {wxStyledTextCtrl, setMarginLeft, 1}},
+ {3100, {wxStyledTextCtrl, getMarginLeft, 0}},
+ {3101, {wxStyledTextCtrl, setMarginRight, 1}},
+ {3102, {wxStyledTextCtrl, getMarginRight, 0}},
+ {3103, {wxStyledTextCtrl, getModify, 0}},
+ {3104, {wxStyledTextCtrl, setSelection, 2}},
+ {3105, {wxStyledTextCtrl, getSelectedText, 0}},
+ {3106, {wxStyledTextCtrl, getTextRange, 2}},
+ {3107, {wxStyledTextCtrl, hideSelection, 1}},
+ {3108, {wxStyledTextCtrl, lineFromPosition, 1}},
+ {3109, {wxStyledTextCtrl, positionFromLine, 1}},
+ {3110, {wxStyledTextCtrl, lineScroll, 2}},
+ {3111, {wxStyledTextCtrl, ensureCaretVisible, 0}},
+ {3112, {wxStyledTextCtrl, replaceSelection, 1}},
+ {3113, {wxStyledTextCtrl, setReadOnly, 1}},
+ {3114, {wxStyledTextCtrl, canPaste, 0}},
+ {3115, {wxStyledTextCtrl, canUndo, 0}},
+ {3116, {wxStyledTextCtrl, emptyUndoBuffer, 0}},
+ {3117, {wxStyledTextCtrl, undo, 0}},
+ {3118, {wxStyledTextCtrl, cut, 0}},
+ {3119, {wxStyledTextCtrl, copy, 0}},
+ {3120, {wxStyledTextCtrl, paste, 0}},
+ {3121, {wxStyledTextCtrl, clear, 0}},
+ {3122, {wxStyledTextCtrl, setText, 1}},
+ {3123, {wxStyledTextCtrl, getText, 0}},
+ {3124, {wxStyledTextCtrl, getTextLength, 0}},
+ {3125, {wxStyledTextCtrl, getOvertype, 0}},
+ {3126, {wxStyledTextCtrl, setCaretWidth, 1}},
+ {3127, {wxStyledTextCtrl, getCaretWidth, 0}},
+ {3128, {wxStyledTextCtrl, setTargetStart, 1}},
+ {3129, {wxStyledTextCtrl, getTargetStart, 0}},
+ {3130, {wxStyledTextCtrl, setTargetEnd, 1}},
+ {3131, {wxStyledTextCtrl, getTargetEnd, 0}},
+ {3132, {wxStyledTextCtrl, replaceTarget, 1}},
+ {3133, {wxStyledTextCtrl, searchInTarget, 1}},
+ {3134, {wxStyledTextCtrl, setSearchFlags, 1}},
+ {3135, {wxStyledTextCtrl, getSearchFlags, 0}},
+ {3136, {wxStyledTextCtrl, callTipShow, 2}},
+ {3137, {wxStyledTextCtrl, callTipCancel, 0}},
+ {3138, {wxStyledTextCtrl, callTipActive, 0}},
+ {3139, {wxStyledTextCtrl, callTipPosAtStart, 0}},
+ {3140, {wxStyledTextCtrl, callTipSetHighlight, 2}},
+ {3141, {wxStyledTextCtrl, callTipSetBackground, 1}},
+ {3142, {wxStyledTextCtrl, callTipSetForeground, 1}},
+ {3143, {wxStyledTextCtrl, callTipSetForegroundHighlight, 1}},
+ {3144, {wxStyledTextCtrl, callTipUseStyle, 1}},
+ {3145, {wxStyledTextCtrl, visibleFromDocLine, 1}},
+ {3146, {wxStyledTextCtrl, docLineFromVisible, 1}},
+ {3147, {wxStyledTextCtrl, wrapCount, 1}},
+ {3148, {wxStyledTextCtrl, setFoldLevel, 2}},
+ {3149, {wxStyledTextCtrl, getFoldLevel, 1}},
+ {3150, {wxStyledTextCtrl, getLastChild, 2}},
+ {3151, {wxStyledTextCtrl, getFoldParent, 1}},
+ {3152, {wxStyledTextCtrl, showLines, 2}},
+ {3153, {wxStyledTextCtrl, hideLines, 2}},
+ {3154, {wxStyledTextCtrl, getLineVisible, 1}},
+ {3155, {wxStyledTextCtrl, setFoldExpanded, 2}},
+ {3156, {wxStyledTextCtrl, getFoldExpanded, 1}},
+ {3157, {wxStyledTextCtrl, toggleFold, 1}},
+ {3158, {wxStyledTextCtrl, ensureVisible, 1}},
+ {3159, {wxStyledTextCtrl, setFoldFlags, 1}},
+ {3160, {wxStyledTextCtrl, ensureVisibleEnforcePolicy, 1}},
+ {3161, {wxStyledTextCtrl, setTabIndents, 1}},
+ {3162, {wxStyledTextCtrl, getTabIndents, 0}},
+ {3163, {wxStyledTextCtrl, setBackSpaceUnIndents, 1}},
+ {3164, {wxStyledTextCtrl, getBackSpaceUnIndents, 0}},
+ {3165, {wxStyledTextCtrl, setMouseDwellTime, 1}},
+ {3166, {wxStyledTextCtrl, getMouseDwellTime, 0}},
+ {3167, {wxStyledTextCtrl, wordStartPosition, 2}},
+ {3168, {wxStyledTextCtrl, wordEndPosition, 2}},
+ {3169, {wxStyledTextCtrl, setWrapMode, 1}},
+ {3170, {wxStyledTextCtrl, getWrapMode, 0}},
+ {3171, {wxStyledTextCtrl, setWrapVisualFlags, 1}},
+ {3172, {wxStyledTextCtrl, getWrapVisualFlags, 0}},
+ {3173, {wxStyledTextCtrl, setWrapVisualFlagsLocation, 1}},
+ {3174, {wxStyledTextCtrl, getWrapVisualFlagsLocation, 0}},
+ {3175, {wxStyledTextCtrl, setWrapStartIndent, 1}},
+ {3176, {wxStyledTextCtrl, getWrapStartIndent, 0}},
+ {3177, {wxStyledTextCtrl, setLayoutCache, 1}},
+ {3178, {wxStyledTextCtrl, getLayoutCache, 0}},
+ {3179, {wxStyledTextCtrl, setScrollWidth, 1}},
+ {3180, {wxStyledTextCtrl, getScrollWidth, 0}},
+ {3181, {wxStyledTextCtrl, textWidth, 2}},
+ {3182, {wxStyledTextCtrl, getEndAtLastLine, 0}},
+ {3183, {wxStyledTextCtrl, textHeight, 1}},
+ {3184, {wxStyledTextCtrl, setUseVerticalScrollBar, 1}},
+ {3185, {wxStyledTextCtrl, getUseVerticalScrollBar, 0}},
+ {3186, {wxStyledTextCtrl, appendText, 1}},
+ {3187, {wxStyledTextCtrl, getTwoPhaseDraw, 0}},
+ {3188, {wxStyledTextCtrl, setTwoPhaseDraw, 1}},
+ {3189, {wxStyledTextCtrl, targetFromSelection, 0}},
+ {3190, {wxStyledTextCtrl, linesJoin, 0}},
+ {3191, {wxStyledTextCtrl, linesSplit, 1}},
+ {3192, {wxStyledTextCtrl, setFoldMarginColour, 2}},
+ {3193, {wxStyledTextCtrl, setFoldMarginHiColour, 2}},
+ {3194, {wxStyledTextCtrl, lineDown, 0}},
+ {3195, {wxStyledTextCtrl, lineDownExtend, 0}},
+ {3196, {wxStyledTextCtrl, lineUp, 0}},
+ {3197, {wxStyledTextCtrl, lineUpExtend, 0}},
+ {3198, {wxStyledTextCtrl, charLeft, 0}},
+ {3199, {wxStyledTextCtrl, charLeftExtend, 0}},
+ {3200, {wxStyledTextCtrl, charRight, 0}},
+ {3201, {wxStyledTextCtrl, charRightExtend, 0}},
+ {3202, {wxStyledTextCtrl, wordLeft, 0}},
+ {3203, {wxStyledTextCtrl, wordLeftExtend, 0}},
+ {3204, {wxStyledTextCtrl, wordRight, 0}},
+ {3205, {wxStyledTextCtrl, wordRightExtend, 0}},
+ {3206, {wxStyledTextCtrl, home, 0}},
+ {3207, {wxStyledTextCtrl, homeExtend, 0}},
+ {3208, {wxStyledTextCtrl, lineEnd, 0}},
+ {3209, {wxStyledTextCtrl, lineEndExtend, 0}},
+ {3210, {wxStyledTextCtrl, documentStart, 0}},
+ {3211, {wxStyledTextCtrl, documentStartExtend, 0}},
+ {3212, {wxStyledTextCtrl, documentEnd, 0}},
+ {3213, {wxStyledTextCtrl, documentEndExtend, 0}},
+ {3214, {wxStyledTextCtrl, pageUp, 0}},
+ {3215, {wxStyledTextCtrl, pageUpExtend, 0}},
+ {3216, {wxStyledTextCtrl, pageDown, 0}},
+ {3217, {wxStyledTextCtrl, pageDownExtend, 0}},
+ {3218, {wxStyledTextCtrl, editToggleOvertype, 0}},
+ {3219, {wxStyledTextCtrl, cancel, 0}},
+ {3220, {wxStyledTextCtrl, deleteBack, 0}},
+ {3221, {wxStyledTextCtrl, tab, 0}},
+ {3222, {wxStyledTextCtrl, backTab, 0}},
+ {3223, {wxStyledTextCtrl, newLine, 0}},
+ {3224, {wxStyledTextCtrl, formFeed, 0}},
+ {3225, {wxStyledTextCtrl, vCHome, 0}},
+ {3226, {wxStyledTextCtrl, vCHomeExtend, 0}},
+ {3227, {wxStyledTextCtrl, zoomIn, 0}},
+ {3228, {wxStyledTextCtrl, zoomOut, 0}},
+ {3229, {wxStyledTextCtrl, delWordLeft, 0}},
+ {3230, {wxStyledTextCtrl, delWordRight, 0}},
+ {3231, {wxStyledTextCtrl, lineCut, 0}},
+ {3232, {wxStyledTextCtrl, lineDelete, 0}},
+ {3233, {wxStyledTextCtrl, lineTranspose, 0}},
+ {3234, {wxStyledTextCtrl, lineDuplicate, 0}},
+ {3235, {wxStyledTextCtrl, lowerCase, 0}},
+ {3236, {wxStyledTextCtrl, upperCase, 0}},
+ {3237, {wxStyledTextCtrl, lineScrollDown, 0}},
+ {3238, {wxStyledTextCtrl, lineScrollUp, 0}},
+ {3239, {wxStyledTextCtrl, deleteBackNotLine, 0}},
+ {3240, {wxStyledTextCtrl, homeDisplay, 0}},
+ {3241, {wxStyledTextCtrl, homeDisplayExtend, 0}},
+ {3242, {wxStyledTextCtrl, lineEndDisplay, 0}},
+ {3243, {wxStyledTextCtrl, lineEndDisplayExtend, 0}},
+ {3244, {wxStyledTextCtrl, homeWrapExtend, 0}},
+ {3245, {wxStyledTextCtrl, lineEndWrap, 0}},
+ {3246, {wxStyledTextCtrl, lineEndWrapExtend, 0}},
+ {3247, {wxStyledTextCtrl, vCHomeWrap, 0}},
+ {3248, {wxStyledTextCtrl, vCHomeWrapExtend, 0}},
+ {3249, {wxStyledTextCtrl, lineCopy, 0}},
+ {3250, {wxStyledTextCtrl, moveCaretInsideView, 0}},
+ {3251, {wxStyledTextCtrl, lineLength, 1}},
+ {3252, {wxStyledTextCtrl, braceHighlight, 2}},
+ {3253, {wxStyledTextCtrl, braceBadLight, 1}},
+ {3254, {wxStyledTextCtrl, braceMatch, 1}},
+ {3255, {wxStyledTextCtrl, getViewEOL, 0}},
+ {3256, {wxStyledTextCtrl, setViewEOL, 1}},
+ {3257, {wxStyledTextCtrl, setModEventMask, 1}},
+ {3258, {wxStyledTextCtrl, getEdgeColumn, 0}},
+ {3259, {wxStyledTextCtrl, setEdgeColumn, 1}},
+ {3260, {wxStyledTextCtrl, getEdgeMode, 0}},
+ {3261, {wxStyledTextCtrl, getEdgeColour, 0}},
+ {3262, {wxStyledTextCtrl, setEdgeColour, 1}},
+ {3263, {wxStyledTextCtrl, searchAnchor, 0}},
+ {3264, {wxStyledTextCtrl, searchNext, 2}},
+ {3265, {wxStyledTextCtrl, searchPrev, 2}},
+ {3266, {wxStyledTextCtrl, linesOnScreen, 0}},
+ {3267, {wxStyledTextCtrl, usePopUp, 1}},
+ {3268, {wxStyledTextCtrl, selectionIsRectangle, 0}},
+ {3269, {wxStyledTextCtrl, setZoom, 1}},
+ {3270, {wxStyledTextCtrl, getZoom, 0}},
+ {3271, {wxStyledTextCtrl, getModEventMask, 0}},
+ {3272, {wxStyledTextCtrl, setSTCFocus, 1}},
+ {3273, {wxStyledTextCtrl, getSTCFocus, 0}},
+ {3274, {wxStyledTextCtrl, setStatus, 1}},
+ {3275, {wxStyledTextCtrl, getStatus, 0}},
+ {3276, {wxStyledTextCtrl, setMouseDownCaptures, 1}},
+ {3277, {wxStyledTextCtrl, getMouseDownCaptures, 0}},
+ {3278, {wxStyledTextCtrl, setSTCCursor, 1}},
+ {3279, {wxStyledTextCtrl, getSTCCursor, 0}},
+ {3280, {wxStyledTextCtrl, setControlCharSymbol, 1}},
+ {3281, {wxStyledTextCtrl, getControlCharSymbol, 0}},
+ {3282, {wxStyledTextCtrl, wordPartLeft, 0}},
+ {3283, {wxStyledTextCtrl, wordPartLeftExtend, 0}},
+ {3284, {wxStyledTextCtrl, wordPartRight, 0}},
+ {3285, {wxStyledTextCtrl, wordPartRightExtend, 0}},
+ {3286, {wxStyledTextCtrl, setVisiblePolicy, 2}},
+ {3287, {wxStyledTextCtrl, delLineLeft, 0}},
+ {3288, {wxStyledTextCtrl, delLineRight, 0}},
+ {3289, {wxStyledTextCtrl, getXOffset, 0}},
+ {3290, {wxStyledTextCtrl, chooseCaretX, 0}},
+ {3291, {wxStyledTextCtrl, setXCaretPolicy, 2}},
+ {3292, {wxStyledTextCtrl, setYCaretPolicy, 2}},
+ {3293, {wxStyledTextCtrl, getPrintWrapMode, 0}},
+ {3294, {wxStyledTextCtrl, setHotspotActiveForeground, 2}},
+ {3295, {wxStyledTextCtrl, setHotspotActiveBackground, 2}},
+ {3296, {wxStyledTextCtrl, setHotspotActiveUnderline, 1}},
+ {3297, {wxStyledTextCtrl, setHotspotSingleLine, 1}},
+ {3298, {wxStyledTextCtrl, paraDownExtend, 0}},
+ {3299, {wxStyledTextCtrl, paraUp, 0}},
+ {3300, {wxStyledTextCtrl, paraUpExtend, 0}},
+ {3301, {wxStyledTextCtrl, positionBefore, 1}},
+ {3302, {wxStyledTextCtrl, positionAfter, 1}},
+ {3303, {wxStyledTextCtrl, copyRange, 2}},
+ {3304, {wxStyledTextCtrl, copyText, 2}},
+ {3305, {wxStyledTextCtrl, setSelectionMode, 1}},
+ {3306, {wxStyledTextCtrl, getSelectionMode, 0}},
+ {3307, {wxStyledTextCtrl, lineDownRectExtend, 0}},
+ {3308, {wxStyledTextCtrl, lineUpRectExtend, 0}},
+ {3309, {wxStyledTextCtrl, charLeftRectExtend, 0}},
+ {3310, {wxStyledTextCtrl, charRightRectExtend, 0}},
+ {3311, {wxStyledTextCtrl, homeRectExtend, 0}},
+ {3312, {wxStyledTextCtrl, vCHomeRectExtend, 0}},
+ {3313, {wxStyledTextCtrl, lineEndRectExtend, 0}},
+ {3314, {wxStyledTextCtrl, pageUpRectExtend, 0}},
+ {3315, {wxStyledTextCtrl, pageDownRectExtend, 0}},
+ {3316, {wxStyledTextCtrl, stutteredPageUp, 0}},
+ {3317, {wxStyledTextCtrl, stutteredPageUpExtend, 0}},
+ {3318, {wxStyledTextCtrl, stutteredPageDown, 0}},
+ {3319, {wxStyledTextCtrl, stutteredPageDownExtend, 0}},
+ {3320, {wxStyledTextCtrl, wordLeftEnd, 0}},
+ {3321, {wxStyledTextCtrl, wordLeftEndExtend, 0}},
+ {3322, {wxStyledTextCtrl, wordRightEnd, 0}},
+ {3323, {wxStyledTextCtrl, wordRightEndExtend, 0}},
+ {3324, {wxStyledTextCtrl, setWhitespaceChars, 1}},
+ {3325, {wxStyledTextCtrl, setCharsDefault, 0}},
+ {3326, {wxStyledTextCtrl, autoCompGetCurrent, 0}},
+ {3327, {wxStyledTextCtrl, allocate, 1}},
+ {3328, {wxStyledTextCtrl, findColumn, 2}},
+ {3329, {wxStyledTextCtrl, getCaretSticky, 0}},
+ {3330, {wxStyledTextCtrl, setCaretSticky, 1}},
+ {3331, {wxStyledTextCtrl, toggleCaretSticky, 0}},
+ {3332, {wxStyledTextCtrl, setPasteConvertEndings, 1}},
+ {3333, {wxStyledTextCtrl, getPasteConvertEndings, 0}},
+ {3334, {wxStyledTextCtrl, selectionDuplicate, 0}},
+ {3335, {wxStyledTextCtrl, setCaretLineBackAlpha, 1}},
+ {3336, {wxStyledTextCtrl, getCaretLineBackAlpha, 0}},
+ {3337, {wxStyledTextCtrl, startRecord, 0}},
+ {3338, {wxStyledTextCtrl, stopRecord, 0}},
+ {3339, {wxStyledTextCtrl, setLexer, 1}},
+ {3340, {wxStyledTextCtrl, getLexer, 0}},
+ {3341, {wxStyledTextCtrl, colourise, 2}},
+ {3342, {wxStyledTextCtrl, setProperty, 2}},
+ {3343, {wxStyledTextCtrl, setKeyWords, 2}},
+ {3344, {wxStyledTextCtrl, setLexerLanguage, 1}},
+ {3345, {wxStyledTextCtrl, getProperty, 1}},
+ {3346, {wxStyledTextCtrl, getStyleBitsNeeded, 0}},
+ {3347, {wxStyledTextCtrl, getCurrentLine, 0}},
+ {3348, {wxStyledTextCtrl, styleSetSpec, 2}},
+ {3349, {wxStyledTextCtrl, styleSetFont, 2}},
+ {3350, {wxStyledTextCtrl, styleSetFontAttr, 7}},
+ {3351, {wxStyledTextCtrl, styleSetCharacterSet, 2}},
+ {3352, {wxStyledTextCtrl, styleSetFontEncoding, 2}},
+ {3353, {wxStyledTextCtrl, cmdKeyExecute, 1}},
+ {3354, {wxStyledTextCtrl, setMargins, 2}},
+ {3355, {wxStyledTextCtrl, getSelection, 2}},
+ {3356, {wxStyledTextCtrl, pointFromPosition, 1}},
+ {3357, {wxStyledTextCtrl, scrollToLine, 1}},
+ {3358, {wxStyledTextCtrl, scrollToColumn, 1}},
+ {3359, {wxStyledTextCtrl, sendMsg, 2}},
+ {3360, {wxStyledTextCtrl, setVScrollBar, 1}},
+ {3361, {wxStyledTextCtrl, setHScrollBar, 1}},
+ {3362, {wxStyledTextCtrl, getLastKeydownProcessed, 0}},
+ {3363, {wxStyledTextCtrl, setLastKeydownProcessed, 1}},
+ {3364, {wxStyledTextCtrl, saveFile, 1}},
+ {3365, {wxStyledTextCtrl, loadFile, 1}},
+ {3366, {wxStyledTextCtrl, doDragOver, 3}},
+ {3367, {wxStyledTextCtrl, doDropText, 3}},
+ {3368, {wxStyledTextCtrl, getUseAntiAliasing, 0}},
+ {3369, {wxStyledTextCtrl, addTextRaw, 1}},
+ {3370, {wxStyledTextCtrl, insertTextRaw, 2}},
+ {3371, {wxStyledTextCtrl, getCurLineRaw, 1}},
+ {3372, {wxStyledTextCtrl, getLineRaw, 1}},
+ {3373, {wxStyledTextCtrl, getSelectedTextRaw, 0}},
+ {3374, {wxStyledTextCtrl, getTextRangeRaw, 2}},
+ {3375, {wxStyledTextCtrl, setTextRaw, 1}},
+ {3376, {wxStyledTextCtrl, getTextRaw, 0}},
+ {3377, {wxStyledTextCtrl, appendTextRaw, 1}},
+ {3378, {wxArtProvider, getBitmap, 2}},
+ {3379, {wxArtProvider, getIcon, 2}},
+ {3380, {wxTreeEvent, getKeyCode, 0}},
+ {3381, {wxTreeEvent, getItem, 0}},
+ {3382, {wxTreeEvent, getKeyEvent, 0}},
+ {3383, {wxTreeEvent, getLabel, 0}},
+ {3384, {wxTreeEvent, getOldItem, 0}},
+ {3385, {wxTreeEvent, getPoint, 0}},
+ {3386, {wxTreeEvent, isEditCancelled, 0}},
+ {3387, {wxTreeEvent, setToolTip, 1}},
+ {3388, {wxNotebookEvent, getOldSelection, 0}},
+ {3389, {wxNotebookEvent, getSelection, 0}},
+ {3390, {wxNotebookEvent, setOldSelection, 1}},
+ {3391, {wxNotebookEvent, setSelection, 1}},
+ {3392, {wxFileDataObject, new, 0}},
+ {3393, {wxFileDataObject, addFile, 1}},
+ {3394, {wxFileDataObject, getFilenames, 0}},
+ {3395, {wxFileDataObject, 'Destroy', undefined}},
+ {3396, {wxTextDataObject, new, 1}},
+ {3397, {wxTextDataObject, getTextLength, 0}},
+ {3398, {wxTextDataObject, getText, 0}},
+ {3399, {wxTextDataObject, setText, 1}},
+ {3400, {wxTextDataObject, 'Destroy', undefined}},
+ {3401, {wxBitmapDataObject, new_1_1, 1}},
+ {3402, {wxBitmapDataObject, new_1_0, 1}},
+ {3403, {wxBitmapDataObject, getBitmap, 0}},
+ {3404, {wxBitmapDataObject, setBitmap, 1}},
+ {3405, {wxBitmapDataObject, 'Destroy', undefined}},
+ {3407, {wxClipboard, new, 0}},
+ {3408, {wxClipboard, destruct, 0}},
+ {3409, {wxClipboard, addData, 1}},
+ {3410, {wxClipboard, clear, 0}},
+ {3411, {wxClipboard, close, 0}},
+ {3412, {wxClipboard, flush, 0}},
+ {3413, {wxClipboard, getData, 1}},
+ {3414, {wxClipboard, isOpened, 0}},
+ {3415, {wxClipboard, open, 0}},
+ {3416, {wxClipboard, setData, 1}},
+ {3418, {wxClipboard, usePrimarySelection, 1}},
+ {3419, {wxClipboard, isSupported, 1}},
+ {3420, {wxClipboard, get, 0}},
+ {3421, {wxSpinEvent, getPosition, 0}},
+ {3422, {wxSpinEvent, setPosition, 1}},
+ {3423, {wxSplitterWindow, new_0, 0}},
+ {3424, {wxSplitterWindow, new_2, 2}},
+ {3425, {wxSplitterWindow, destruct, 0}},
+ {3426, {wxSplitterWindow, create, 2}},
+ {3427, {wxSplitterWindow, getMinimumPaneSize, 0}},
+ {3428, {wxSplitterWindow, getSashGravity, 0}},
+ {3429, {wxSplitterWindow, getSashPosition, 0}},
+ {3430, {wxSplitterWindow, getSplitMode, 0}},
+ {3431, {wxSplitterWindow, getWindow1, 0}},
+ {3432, {wxSplitterWindow, getWindow2, 0}},
+ {3433, {wxSplitterWindow, initialize, 1}},
+ {3434, {wxSplitterWindow, isSplit, 0}},
+ {3435, {wxSplitterWindow, replaceWindow, 2}},
+ {3436, {wxSplitterWindow, setSashGravity, 1}},
+ {3437, {wxSplitterWindow, setSashPosition, 2}},
+ {3438, {wxSplitterWindow, setSashSize, 1}},
+ {3439, {wxSplitterWindow, setMinimumPaneSize, 1}},
+ {3440, {wxSplitterWindow, setSplitMode, 1}},
+ {3441, {wxSplitterWindow, splitHorizontally, 3}},
+ {3442, {wxSplitterWindow, splitVertically, 3}},
+ {3443, {wxSplitterWindow, unsplit, 1}},
+ {3444, {wxSplitterWindow, updateSize, 0}},
+ {3445, {wxSplitterEvent, getSashPosition, 0}},
+ {3446, {wxSplitterEvent, getX, 0}},
+ {3447, {wxSplitterEvent, getY, 0}},
+ {3448, {wxSplitterEvent, getWindowBeingRemoved, 0}},
+ {3449, {wxSplitterEvent, setSashPosition, 1}},
+ {3450, {wxHtmlWindow, new_0, 0}},
+ {3451, {wxHtmlWindow, new_2, 2}},
+ {3452, {wxHtmlWindow, appendToPage, 1}},
+ {3453, {wxHtmlWindow, getOpenedAnchor, 0}},
+ {3454, {wxHtmlWindow, getOpenedPage, 0}},
+ {3455, {wxHtmlWindow, getOpenedPageTitle, 0}},
+ {3456, {wxHtmlWindow, getRelatedFrame, 0}},
+ {3457, {wxHtmlWindow, historyBack, 0}},
+ {3458, {wxHtmlWindow, historyCanBack, 0}},
+ {3459, {wxHtmlWindow, historyCanForward, 0}},
+ {3460, {wxHtmlWindow, historyClear, 0}},
+ {3461, {wxHtmlWindow, historyForward, 0}},
+ {3462, {wxHtmlWindow, loadFile, 1}},
+ {3463, {wxHtmlWindow, loadPage, 1}},
+ {3464, {wxHtmlWindow, selectAll, 0}},
+ {3465, {wxHtmlWindow, selectionToText, 0}},
+ {3466, {wxHtmlWindow, selectLine, 1}},
+ {3467, {wxHtmlWindow, selectWord, 1}},
+ {3468, {wxHtmlWindow, setBorders, 1}},
+ {3469, {wxHtmlWindow, setFonts, 3}},
+ {3470, {wxHtmlWindow, setPage, 1}},
+ {3471, {wxHtmlWindow, setRelatedFrame, 2}},
+ {3472, {wxHtmlWindow, setRelatedStatusBar, 1}},
+ {3473, {wxHtmlWindow, toText, 0}},
+ {3474, {wxHtmlWindow, 'Destroy', undefined}},
+ {3475, {wxHtmlLinkEvent, getLinkInfo, 0}},
+ {3476, {wxSystemSettings, getColour, 1}},
+ {3477, {wxSystemSettings, getFont, 1}},
+ {3478, {wxSystemSettings, getMetric, 2}},
+ {3479, {wxSystemSettings, getScreenType, 0}},
+ {3480, {wxAuiNotebookEvent, setSelection, 1}},
+ {3481, {wxAuiNotebookEvent, getSelection, 0}},
+ {3482, {wxAuiNotebookEvent, setOldSelection, 1}},
+ {3483, {wxAuiNotebookEvent, getOldSelection, 0}},
+ {3484, {wxAuiNotebookEvent, setDragSource, 1}},
+ {3485, {wxAuiNotebookEvent, getDragSource, 0}},
+ {3486, {wxAuiManagerEvent, setManager, 1}},
+ {3487, {wxAuiManagerEvent, getManager, 0}},
+ {3488, {wxAuiManagerEvent, setPane, 1}},
+ {3489, {wxAuiManagerEvent, getPane, 0}},
+ {3490, {wxAuiManagerEvent, setButton, 1}},
+ {3491, {wxAuiManagerEvent, getButton, 0}},
+ {3492, {wxAuiManagerEvent, setDC, 1}},
+ {3493, {wxAuiManagerEvent, getDC, 0}},
+ {3494, {wxAuiManagerEvent, veto, 1}},
+ {3495, {wxAuiManagerEvent, getVeto, 0}},
+ {3496, {wxAuiManagerEvent, setCanVeto, 1}},
+ {3497, {wxAuiManagerEvent, canVeto, 0}},
+ {3498, {wxLogNull, new, 0}},
+ {3499, {wxLogNull, 'Destroy', undefined}},
{-1, {mod, func, -1}}
].
diff --git a/lib/wx/src/gen/wxe_funcs.hrl b/lib/wx/src/gen/wxe_funcs.hrl
index 7b5ca229c8..cf672644c6 100644
--- a/lib/wx/src/gen/wxe_funcs.hrl
+++ b/lib/wx/src/gen/wxe_funcs.hrl
@@ -1834,1442 +1834,1447 @@
-define(wxTreeCtrl_Delete, 2007).
-define(wxTreeCtrl_DeleteAllItems, 2008).
-define(wxTreeCtrl_DeleteChildren, 2009).
--define(wxTreeCtrl_EnsureVisible, 2010).
--define(wxTreeCtrl_Expand, 2011).
--define(wxTreeCtrl_GetBoundingRect, 2012).
--define(wxTreeCtrl_GetChildrenCount, 2014).
--define(wxTreeCtrl_GetCount, 2015).
--define(wxTreeCtrl_GetEditControl, 2016).
--define(wxTreeCtrl_GetFirstChild, 2017).
--define(wxTreeCtrl_GetNextChild, 2018).
--define(wxTreeCtrl_GetFirstVisibleItem, 2019).
--define(wxTreeCtrl_GetImageList, 2020).
--define(wxTreeCtrl_GetIndent, 2021).
--define(wxTreeCtrl_GetItemBackgroundColour, 2022).
--define(wxTreeCtrl_GetItemData, 2023).
--define(wxTreeCtrl_GetItemFont, 2024).
--define(wxTreeCtrl_GetItemImage_1, 2025).
--define(wxTreeCtrl_GetItemImage_2, 2026).
--define(wxTreeCtrl_GetItemText, 2027).
--define(wxTreeCtrl_GetItemTextColour, 2028).
--define(wxTreeCtrl_GetLastChild, 2029).
--define(wxTreeCtrl_GetNextSibling, 2030).
--define(wxTreeCtrl_GetNextVisible, 2031).
--define(wxTreeCtrl_GetItemParent, 2032).
--define(wxTreeCtrl_GetPrevSibling, 2033).
--define(wxTreeCtrl_GetPrevVisible, 2034).
--define(wxTreeCtrl_GetRootItem, 2035).
--define(wxTreeCtrl_GetSelection, 2036).
--define(wxTreeCtrl_GetSelections, 2037).
--define(wxTreeCtrl_GetStateImageList, 2038).
--define(wxTreeCtrl_HitTest, 2039).
--define(wxTreeCtrl_InsertItem, 2041).
--define(wxTreeCtrl_IsBold, 2042).
--define(wxTreeCtrl_IsExpanded, 2043).
--define(wxTreeCtrl_IsSelected, 2044).
--define(wxTreeCtrl_IsVisible, 2045).
--define(wxTreeCtrl_ItemHasChildren, 2046).
--define(wxTreeCtrl_PrependItem, 2047).
--define(wxTreeCtrl_ScrollTo, 2048).
--define(wxTreeCtrl_SelectItem_1, 2049).
--define(wxTreeCtrl_SelectItem_2, 2050).
--define(wxTreeCtrl_SetIndent, 2051).
--define(wxTreeCtrl_SetImageList, 2052).
--define(wxTreeCtrl_SetItemBackgroundColour, 2053).
--define(wxTreeCtrl_SetItemBold, 2054).
--define(wxTreeCtrl_SetItemData, 2055).
--define(wxTreeCtrl_SetItemDropHighlight, 2056).
--define(wxTreeCtrl_SetItemFont, 2057).
--define(wxTreeCtrl_SetItemHasChildren, 2058).
--define(wxTreeCtrl_SetItemImage_2, 2059).
--define(wxTreeCtrl_SetItemImage_3, 2060).
--define(wxTreeCtrl_SetItemText, 2061).
--define(wxTreeCtrl_SetItemTextColour, 2062).
--define(wxTreeCtrl_SetStateImageList, 2063).
--define(wxTreeCtrl_SetWindowStyle, 2064).
--define(wxTreeCtrl_SortChildren, 2065).
--define(wxTreeCtrl_Toggle, 2066).
--define(wxTreeCtrl_ToggleItemSelection, 2067).
--define(wxTreeCtrl_Unselect, 2068).
--define(wxTreeCtrl_UnselectAll, 2069).
--define(wxTreeCtrl_UnselectItem, 2070).
--define(wxScrollBar_new_0, 2071).
--define(wxScrollBar_new_3, 2072).
--define(wxScrollBar_destruct, 2073).
--define(wxScrollBar_Create, 2074).
--define(wxScrollBar_GetRange, 2075).
--define(wxScrollBar_GetPageSize, 2076).
--define(wxScrollBar_GetThumbPosition, 2077).
--define(wxScrollBar_GetThumbSize, 2078).
--define(wxScrollBar_SetThumbPosition, 2079).
--define(wxScrollBar_SetScrollbar, 2080).
--define(wxSpinButton_new_2, 2082).
--define(wxSpinButton_new_0, 2083).
--define(wxSpinButton_Create, 2084).
--define(wxSpinButton_GetMax, 2085).
--define(wxSpinButton_GetMin, 2086).
--define(wxSpinButton_GetValue, 2087).
--define(wxSpinButton_SetRange, 2088).
--define(wxSpinButton_SetValue, 2089).
--define(wxSpinButton_destroy, 2090).
--define(wxSpinCtrl_new_0, 2091).
--define(wxSpinCtrl_new_2, 2092).
--define(wxSpinCtrl_Create, 2094).
--define(wxSpinCtrl_SetValue_1_1, 2097).
--define(wxSpinCtrl_SetValue_1_0, 2098).
--define(wxSpinCtrl_GetValue, 2100).
--define(wxSpinCtrl_SetRange, 2102).
--define(wxSpinCtrl_SetSelection, 2103).
--define(wxSpinCtrl_GetMin, 2105).
--define(wxSpinCtrl_GetMax, 2107).
--define(wxSpinCtrl_destroy, 2108).
--define(wxStaticText_new_0, 2109).
--define(wxStaticText_new_4, 2110).
--define(wxStaticText_Create, 2111).
--define(wxStaticText_GetLabel, 2112).
--define(wxStaticText_SetLabel, 2113).
--define(wxStaticText_Wrap, 2114).
--define(wxStaticText_destroy, 2115).
--define(wxStaticBitmap_new_0, 2116).
--define(wxStaticBitmap_new_4, 2117).
--define(wxStaticBitmap_Create, 2118).
--define(wxStaticBitmap_GetBitmap, 2119).
--define(wxStaticBitmap_SetBitmap, 2120).
--define(wxStaticBitmap_destroy, 2121).
--define(wxRadioBox_new, 2122).
--define(wxRadioBox_destruct, 2124).
--define(wxRadioBox_Create, 2125).
--define(wxRadioBox_Enable_2, 2126).
--define(wxRadioBox_Enable_1, 2127).
--define(wxRadioBox_GetSelection, 2128).
--define(wxRadioBox_GetString, 2129).
--define(wxRadioBox_SetSelection, 2130).
--define(wxRadioBox_Show_2, 2131).
--define(wxRadioBox_Show_1, 2132).
--define(wxRadioBox_GetColumnCount, 2133).
--define(wxRadioBox_GetItemHelpText, 2134).
--define(wxRadioBox_GetItemToolTip, 2135).
--define(wxRadioBox_GetItemFromPoint, 2137).
--define(wxRadioBox_GetRowCount, 2138).
--define(wxRadioBox_IsItemEnabled, 2139).
--define(wxRadioBox_IsItemShown, 2140).
--define(wxRadioBox_SetItemHelpText, 2141).
--define(wxRadioBox_SetItemToolTip, 2142).
--define(wxRadioButton_new_0, 2143).
--define(wxRadioButton_new_4, 2144).
--define(wxRadioButton_Create, 2145).
--define(wxRadioButton_GetValue, 2146).
--define(wxRadioButton_SetValue, 2147).
--define(wxRadioButton_destroy, 2148).
--define(wxSlider_new_6, 2150).
--define(wxSlider_new_0, 2151).
--define(wxSlider_Create, 2152).
--define(wxSlider_GetLineSize, 2153).
--define(wxSlider_GetMax, 2154).
--define(wxSlider_GetMin, 2155).
--define(wxSlider_GetPageSize, 2156).
--define(wxSlider_GetThumbLength, 2157).
--define(wxSlider_GetValue, 2158).
--define(wxSlider_SetLineSize, 2159).
--define(wxSlider_SetPageSize, 2160).
--define(wxSlider_SetRange, 2161).
--define(wxSlider_SetThumbLength, 2162).
--define(wxSlider_SetValue, 2163).
--define(wxSlider_destroy, 2164).
--define(wxDialog_new_4, 2166).
--define(wxDialog_new_0, 2167).
--define(wxDialog_destruct, 2169).
--define(wxDialog_Create, 2170).
--define(wxDialog_CreateButtonSizer, 2171).
--define(wxDialog_CreateStdDialogButtonSizer, 2172).
--define(wxDialog_EndModal, 2173).
--define(wxDialog_GetAffirmativeId, 2174).
--define(wxDialog_GetReturnCode, 2175).
--define(wxDialog_IsModal, 2176).
--define(wxDialog_SetAffirmativeId, 2177).
--define(wxDialog_SetReturnCode, 2178).
--define(wxDialog_Show, 2179).
--define(wxDialog_ShowModal, 2180).
--define(wxColourDialog_new_0, 2181).
--define(wxColourDialog_new_2, 2182).
--define(wxColourDialog_destruct, 2183).
--define(wxColourDialog_Create, 2184).
--define(wxColourDialog_GetColourData, 2185).
--define(wxColourData_new_0, 2186).
--define(wxColourData_new_1, 2187).
--define(wxColourData_destruct, 2188).
--define(wxColourData_GetChooseFull, 2189).
--define(wxColourData_GetColour, 2190).
--define(wxColourData_GetCustomColour, 2192).
--define(wxColourData_SetChooseFull, 2193).
--define(wxColourData_SetColour, 2194).
--define(wxColourData_SetCustomColour, 2195).
--define(wxPalette_new_0, 2196).
--define(wxPalette_new_4, 2197).
--define(wxPalette_destruct, 2199).
--define(wxPalette_Create, 2200).
--define(wxPalette_GetColoursCount, 2201).
--define(wxPalette_GetPixel, 2202).
--define(wxPalette_GetRGB, 2203).
--define(wxPalette_IsOk, 2204).
--define(wxDirDialog_new, 2208).
--define(wxDirDialog_destruct, 2209).
--define(wxDirDialog_GetPath, 2210).
--define(wxDirDialog_GetMessage, 2211).
--define(wxDirDialog_SetMessage, 2212).
--define(wxDirDialog_SetPath, 2213).
--define(wxFileDialog_new, 2217).
--define(wxFileDialog_destruct, 2218).
--define(wxFileDialog_GetDirectory, 2219).
--define(wxFileDialog_GetFilename, 2220).
--define(wxFileDialog_GetFilenames, 2221).
--define(wxFileDialog_GetFilterIndex, 2222).
--define(wxFileDialog_GetMessage, 2223).
--define(wxFileDialog_GetPath, 2224).
--define(wxFileDialog_GetPaths, 2225).
--define(wxFileDialog_GetWildcard, 2226).
--define(wxFileDialog_SetDirectory, 2227).
--define(wxFileDialog_SetFilename, 2228).
--define(wxFileDialog_SetFilterIndex, 2229).
--define(wxFileDialog_SetMessage, 2230).
--define(wxFileDialog_SetPath, 2231).
--define(wxFileDialog_SetWildcard, 2232).
--define(wxPickerBase_SetInternalMargin, 2233).
--define(wxPickerBase_GetInternalMargin, 2234).
--define(wxPickerBase_SetTextCtrlProportion, 2235).
--define(wxPickerBase_SetPickerCtrlProportion, 2236).
--define(wxPickerBase_GetTextCtrlProportion, 2237).
--define(wxPickerBase_GetPickerCtrlProportion, 2238).
--define(wxPickerBase_HasTextCtrl, 2239).
--define(wxPickerBase_GetTextCtrl, 2240).
--define(wxPickerBase_IsTextCtrlGrowable, 2241).
--define(wxPickerBase_SetPickerCtrlGrowable, 2242).
--define(wxPickerBase_SetTextCtrlGrowable, 2243).
--define(wxPickerBase_IsPickerCtrlGrowable, 2244).
--define(wxFilePickerCtrl_new_0, 2245).
--define(wxFilePickerCtrl_new_3, 2246).
--define(wxFilePickerCtrl_Create, 2247).
--define(wxFilePickerCtrl_GetPath, 2248).
--define(wxFilePickerCtrl_SetPath, 2249).
--define(wxFilePickerCtrl_destroy, 2250).
--define(wxDirPickerCtrl_new_0, 2251).
--define(wxDirPickerCtrl_new_3, 2252).
--define(wxDirPickerCtrl_Create, 2253).
--define(wxDirPickerCtrl_GetPath, 2254).
--define(wxDirPickerCtrl_SetPath, 2255).
--define(wxDirPickerCtrl_destroy, 2256).
--define(wxColourPickerCtrl_new_0, 2257).
--define(wxColourPickerCtrl_new_3, 2258).
--define(wxColourPickerCtrl_Create, 2259).
--define(wxColourPickerCtrl_GetColour, 2260).
--define(wxColourPickerCtrl_SetColour_1_1, 2261).
--define(wxColourPickerCtrl_SetColour_1_0, 2262).
--define(wxColourPickerCtrl_destroy, 2263).
--define(wxDatePickerCtrl_new_0, 2264).
--define(wxDatePickerCtrl_new_3, 2265).
--define(wxDatePickerCtrl_GetRange, 2266).
--define(wxDatePickerCtrl_GetValue, 2267).
--define(wxDatePickerCtrl_SetRange, 2268).
--define(wxDatePickerCtrl_SetValue, 2269).
--define(wxDatePickerCtrl_destroy, 2270).
--define(wxFontPickerCtrl_new_0, 2271).
--define(wxFontPickerCtrl_new_3, 2272).
--define(wxFontPickerCtrl_Create, 2273).
--define(wxFontPickerCtrl_GetSelectedFont, 2274).
--define(wxFontPickerCtrl_SetSelectedFont, 2275).
--define(wxFontPickerCtrl_GetMaxPointSize, 2276).
--define(wxFontPickerCtrl_SetMaxPointSize, 2277).
--define(wxFontPickerCtrl_destroy, 2278).
--define(wxFindReplaceDialog_new_0, 2281).
--define(wxFindReplaceDialog_new_4, 2282).
--define(wxFindReplaceDialog_destruct, 2283).
--define(wxFindReplaceDialog_Create, 2284).
--define(wxFindReplaceDialog_GetData, 2285).
--define(wxFindReplaceData_new_0, 2286).
--define(wxFindReplaceData_new_1, 2287).
--define(wxFindReplaceData_GetFindString, 2288).
--define(wxFindReplaceData_GetReplaceString, 2289).
--define(wxFindReplaceData_GetFlags, 2290).
--define(wxFindReplaceData_SetFlags, 2291).
--define(wxFindReplaceData_SetFindString, 2292).
--define(wxFindReplaceData_SetReplaceString, 2293).
--define(wxFindReplaceData_destroy, 2294).
--define(wxMultiChoiceDialog_new_0, 2295).
--define(wxMultiChoiceDialog_new_5, 2297).
--define(wxMultiChoiceDialog_GetSelections, 2298).
--define(wxMultiChoiceDialog_SetSelections, 2299).
--define(wxMultiChoiceDialog_destroy, 2300).
--define(wxSingleChoiceDialog_new_0, 2301).
--define(wxSingleChoiceDialog_new_5, 2303).
--define(wxSingleChoiceDialog_GetSelection, 2304).
--define(wxSingleChoiceDialog_GetStringSelection, 2305).
--define(wxSingleChoiceDialog_SetSelection, 2306).
--define(wxSingleChoiceDialog_destroy, 2307).
--define(wxTextEntryDialog_new, 2308).
--define(wxTextEntryDialog_GetValue, 2309).
--define(wxTextEntryDialog_SetValue, 2310).
--define(wxTextEntryDialog_destroy, 2311).
--define(wxPasswordEntryDialog_new, 2312).
--define(wxPasswordEntryDialog_destroy, 2313).
--define(wxFontData_new_0, 2314).
--define(wxFontData_new_1, 2315).
--define(wxFontData_destruct, 2316).
--define(wxFontData_EnableEffects, 2317).
--define(wxFontData_GetAllowSymbols, 2318).
--define(wxFontData_GetColour, 2319).
--define(wxFontData_GetChosenFont, 2320).
--define(wxFontData_GetEnableEffects, 2321).
--define(wxFontData_GetInitialFont, 2322).
--define(wxFontData_GetShowHelp, 2323).
--define(wxFontData_SetAllowSymbols, 2324).
--define(wxFontData_SetChosenFont, 2325).
--define(wxFontData_SetColour, 2326).
--define(wxFontData_SetInitialFont, 2327).
--define(wxFontData_SetRange, 2328).
--define(wxFontData_SetShowHelp, 2329).
--define(wxFontDialog_new_0, 2333).
--define(wxFontDialog_new_2, 2335).
--define(wxFontDialog_Create, 2337).
--define(wxFontDialog_GetFontData, 2338).
--define(wxFontDialog_destroy, 2340).
--define(wxProgressDialog_new, 2341).
--define(wxProgressDialog_destruct, 2342).
--define(wxProgressDialog_Resume, 2343).
--define(wxProgressDialog_Update_2, 2344).
--define(wxProgressDialog_Update_0, 2345).
--define(wxMessageDialog_new, 2346).
--define(wxMessageDialog_destruct, 2347).
--define(wxPageSetupDialog_new, 2348).
--define(wxPageSetupDialog_destruct, 2349).
--define(wxPageSetupDialog_GetPageSetupData, 2350).
--define(wxPageSetupDialog_ShowModal, 2351).
--define(wxPageSetupDialogData_new_0, 2352).
--define(wxPageSetupDialogData_new_1_0, 2353).
--define(wxPageSetupDialogData_new_1_1, 2354).
--define(wxPageSetupDialogData_destruct, 2355).
--define(wxPageSetupDialogData_EnableHelp, 2356).
--define(wxPageSetupDialogData_EnableMargins, 2357).
--define(wxPageSetupDialogData_EnableOrientation, 2358).
--define(wxPageSetupDialogData_EnablePaper, 2359).
--define(wxPageSetupDialogData_EnablePrinter, 2360).
--define(wxPageSetupDialogData_GetDefaultMinMargins, 2361).
--define(wxPageSetupDialogData_GetEnableMargins, 2362).
--define(wxPageSetupDialogData_GetEnableOrientation, 2363).
--define(wxPageSetupDialogData_GetEnablePaper, 2364).
--define(wxPageSetupDialogData_GetEnablePrinter, 2365).
--define(wxPageSetupDialogData_GetEnableHelp, 2366).
--define(wxPageSetupDialogData_GetDefaultInfo, 2367).
--define(wxPageSetupDialogData_GetMarginTopLeft, 2368).
--define(wxPageSetupDialogData_GetMarginBottomRight, 2369).
--define(wxPageSetupDialogData_GetMinMarginTopLeft, 2370).
--define(wxPageSetupDialogData_GetMinMarginBottomRight, 2371).
--define(wxPageSetupDialogData_GetPaperId, 2372).
--define(wxPageSetupDialogData_GetPaperSize, 2373).
--define(wxPageSetupDialogData_GetPrintData, 2375).
--define(wxPageSetupDialogData_IsOk, 2376).
--define(wxPageSetupDialogData_SetDefaultInfo, 2377).
--define(wxPageSetupDialogData_SetDefaultMinMargins, 2378).
--define(wxPageSetupDialogData_SetMarginTopLeft, 2379).
--define(wxPageSetupDialogData_SetMarginBottomRight, 2380).
--define(wxPageSetupDialogData_SetMinMarginTopLeft, 2381).
--define(wxPageSetupDialogData_SetMinMarginBottomRight, 2382).
--define(wxPageSetupDialogData_SetPaperId, 2383).
--define(wxPageSetupDialogData_SetPaperSize_1_1, 2384).
--define(wxPageSetupDialogData_SetPaperSize_1_0, 2385).
--define(wxPageSetupDialogData_SetPrintData, 2386).
--define(wxPrintDialog_new_2_0, 2387).
--define(wxPrintDialog_new_2_1, 2388).
--define(wxPrintDialog_destruct, 2389).
--define(wxPrintDialog_GetPrintDialogData, 2390).
--define(wxPrintDialog_GetPrintDC, 2391).
--define(wxPrintDialogData_new_0, 2392).
--define(wxPrintDialogData_new_1_1, 2393).
--define(wxPrintDialogData_new_1_0, 2394).
--define(wxPrintDialogData_destruct, 2395).
--define(wxPrintDialogData_EnableHelp, 2396).
--define(wxPrintDialogData_EnablePageNumbers, 2397).
--define(wxPrintDialogData_EnablePrintToFile, 2398).
--define(wxPrintDialogData_EnableSelection, 2399).
--define(wxPrintDialogData_GetAllPages, 2400).
--define(wxPrintDialogData_GetCollate, 2401).
--define(wxPrintDialogData_GetFromPage, 2402).
--define(wxPrintDialogData_GetMaxPage, 2403).
--define(wxPrintDialogData_GetMinPage, 2404).
--define(wxPrintDialogData_GetNoCopies, 2405).
--define(wxPrintDialogData_GetPrintData, 2406).
--define(wxPrintDialogData_GetPrintToFile, 2407).
--define(wxPrintDialogData_GetSelection, 2408).
--define(wxPrintDialogData_GetToPage, 2409).
--define(wxPrintDialogData_IsOk, 2410).
--define(wxPrintDialogData_SetCollate, 2411).
--define(wxPrintDialogData_SetFromPage, 2412).
--define(wxPrintDialogData_SetMaxPage, 2413).
--define(wxPrintDialogData_SetMinPage, 2414).
--define(wxPrintDialogData_SetNoCopies, 2415).
--define(wxPrintDialogData_SetPrintData, 2416).
--define(wxPrintDialogData_SetPrintToFile, 2417).
--define(wxPrintDialogData_SetSelection, 2418).
--define(wxPrintDialogData_SetToPage, 2419).
--define(wxPrintData_new_0, 2420).
--define(wxPrintData_new_1, 2421).
--define(wxPrintData_destruct, 2422).
--define(wxPrintData_GetCollate, 2423).
--define(wxPrintData_GetBin, 2424).
--define(wxPrintData_GetColour, 2425).
--define(wxPrintData_GetDuplex, 2426).
--define(wxPrintData_GetNoCopies, 2427).
--define(wxPrintData_GetOrientation, 2428).
--define(wxPrintData_GetPaperId, 2429).
--define(wxPrintData_GetPrinterName, 2430).
--define(wxPrintData_GetQuality, 2431).
--define(wxPrintData_IsOk, 2432).
--define(wxPrintData_SetBin, 2433).
--define(wxPrintData_SetCollate, 2434).
--define(wxPrintData_SetColour, 2435).
--define(wxPrintData_SetDuplex, 2436).
--define(wxPrintData_SetNoCopies, 2437).
--define(wxPrintData_SetOrientation, 2438).
--define(wxPrintData_SetPaperId, 2439).
--define(wxPrintData_SetPrinterName, 2440).
--define(wxPrintData_SetQuality, 2441).
--define(wxPrintPreview_new_2, 2444).
--define(wxPrintPreview_new_3, 2445).
--define(wxPrintPreview_destruct, 2447).
--define(wxPrintPreview_GetCanvas, 2448).
--define(wxPrintPreview_GetCurrentPage, 2449).
--define(wxPrintPreview_GetFrame, 2450).
--define(wxPrintPreview_GetMaxPage, 2451).
--define(wxPrintPreview_GetMinPage, 2452).
--define(wxPrintPreview_GetPrintout, 2453).
--define(wxPrintPreview_GetPrintoutForPrinting, 2454).
--define(wxPrintPreview_IsOk, 2455).
--define(wxPrintPreview_PaintPage, 2456).
--define(wxPrintPreview_Print, 2457).
--define(wxPrintPreview_RenderPage, 2458).
--define(wxPrintPreview_SetCanvas, 2459).
--define(wxPrintPreview_SetCurrentPage, 2460).
--define(wxPrintPreview_SetFrame, 2461).
--define(wxPrintPreview_SetPrintout, 2462).
--define(wxPrintPreview_SetZoom, 2463).
--define(wxPreviewFrame_new, 2464).
--define(wxPreviewFrame_destruct, 2465).
--define(wxPreviewFrame_CreateControlBar, 2466).
--define(wxPreviewFrame_CreateCanvas, 2467).
--define(wxPreviewFrame_Initialize, 2468).
--define(wxPreviewFrame_OnCloseWindow, 2469).
--define(wxPreviewControlBar_new, 2470).
--define(wxPreviewControlBar_destruct, 2471).
--define(wxPreviewControlBar_CreateButtons, 2472).
--define(wxPreviewControlBar_GetPrintPreview, 2473).
--define(wxPreviewControlBar_GetZoomControl, 2474).
--define(wxPreviewControlBar_SetZoomControl, 2475).
--define(wxPrinter_new, 2477).
--define(wxPrinter_CreateAbortWindow, 2478).
--define(wxPrinter_GetAbort, 2479).
--define(wxPrinter_GetLastError, 2480).
--define(wxPrinter_GetPrintDialogData, 2481).
--define(wxPrinter_Print, 2482).
--define(wxPrinter_PrintDialog, 2483).
--define(wxPrinter_ReportError, 2484).
--define(wxPrinter_Setup, 2485).
--define(wxPrinter_destroy, 2486).
--define(wxXmlResource_new_1, 2487).
--define(wxXmlResource_new_2, 2488).
--define(wxXmlResource_destruct, 2489).
--define(wxXmlResource_AttachUnknownControl, 2490).
--define(wxXmlResource_ClearHandlers, 2491).
--define(wxXmlResource_CompareVersion, 2492).
--define(wxXmlResource_Get, 2493).
--define(wxXmlResource_GetFlags, 2494).
--define(wxXmlResource_GetVersion, 2495).
--define(wxXmlResource_GetXRCID, 2496).
--define(wxXmlResource_InitAllHandlers, 2497).
--define(wxXmlResource_Load, 2498).
--define(wxXmlResource_LoadBitmap, 2499).
--define(wxXmlResource_LoadDialog_2, 2500).
--define(wxXmlResource_LoadDialog_3, 2501).
--define(wxXmlResource_LoadFrame_2, 2502).
--define(wxXmlResource_LoadFrame_3, 2503).
--define(wxXmlResource_LoadIcon, 2504).
--define(wxXmlResource_LoadMenu, 2505).
--define(wxXmlResource_LoadMenuBar_2, 2506).
--define(wxXmlResource_LoadMenuBar_1, 2507).
--define(wxXmlResource_LoadPanel_2, 2508).
--define(wxXmlResource_LoadPanel_3, 2509).
--define(wxXmlResource_LoadToolBar, 2510).
--define(wxXmlResource_Set, 2511).
--define(wxXmlResource_SetFlags, 2512).
--define(wxXmlResource_Unload, 2513).
--define(wxXmlResource_xrcctrl, 2514).
--define(wxHtmlEasyPrinting_new, 2515).
--define(wxHtmlEasyPrinting_destruct, 2516).
--define(wxHtmlEasyPrinting_GetPrintData, 2517).
--define(wxHtmlEasyPrinting_GetPageSetupData, 2518).
--define(wxHtmlEasyPrinting_PreviewFile, 2519).
--define(wxHtmlEasyPrinting_PreviewText, 2520).
--define(wxHtmlEasyPrinting_PrintFile, 2521).
--define(wxHtmlEasyPrinting_PrintText, 2522).
--define(wxHtmlEasyPrinting_PageSetup, 2523).
--define(wxHtmlEasyPrinting_SetFonts, 2524).
--define(wxHtmlEasyPrinting_SetHeader, 2525).
--define(wxHtmlEasyPrinting_SetFooter, 2526).
--define(wxGLCanvas_new_2, 2528).
--define(wxGLCanvas_new_3_1, 2529).
--define(wxGLCanvas_new_3_0, 2530).
--define(wxGLCanvas_GetContext, 2531).
--define(wxGLCanvas_SetCurrent, 2533).
--define(wxGLCanvas_SwapBuffers, 2534).
--define(wxGLCanvas_destroy, 2535).
--define(wxAuiManager_new, 2536).
--define(wxAuiManager_destruct, 2537).
--define(wxAuiManager_AddPane_2_1, 2538).
--define(wxAuiManager_AddPane_3, 2539).
--define(wxAuiManager_AddPane_2_0, 2540).
--define(wxAuiManager_DetachPane, 2541).
--define(wxAuiManager_GetAllPanes, 2542).
--define(wxAuiManager_GetArtProvider, 2543).
--define(wxAuiManager_GetDockSizeConstraint, 2544).
--define(wxAuiManager_GetFlags, 2545).
--define(wxAuiManager_GetManagedWindow, 2546).
--define(wxAuiManager_GetManager, 2547).
--define(wxAuiManager_GetPane_1_1, 2548).
--define(wxAuiManager_GetPane_1_0, 2549).
--define(wxAuiManager_HideHint, 2550).
--define(wxAuiManager_InsertPane, 2551).
--define(wxAuiManager_LoadPaneInfo, 2552).
--define(wxAuiManager_LoadPerspective, 2553).
--define(wxAuiManager_SavePaneInfo, 2554).
--define(wxAuiManager_SavePerspective, 2555).
--define(wxAuiManager_SetArtProvider, 2556).
--define(wxAuiManager_SetDockSizeConstraint, 2557).
--define(wxAuiManager_SetFlags, 2558).
--define(wxAuiManager_SetManagedWindow, 2559).
--define(wxAuiManager_ShowHint, 2560).
--define(wxAuiManager_UnInit, 2561).
--define(wxAuiManager_Update, 2562).
--define(wxAuiPaneInfo_new_0, 2563).
--define(wxAuiPaneInfo_new_1, 2564).
--define(wxAuiPaneInfo_destruct, 2565).
--define(wxAuiPaneInfo_BestSize_1, 2566).
--define(wxAuiPaneInfo_BestSize_2, 2567).
--define(wxAuiPaneInfo_Bottom, 2568).
--define(wxAuiPaneInfo_BottomDockable, 2569).
--define(wxAuiPaneInfo_Caption, 2570).
--define(wxAuiPaneInfo_CaptionVisible, 2571).
--define(wxAuiPaneInfo_Centre, 2572).
--define(wxAuiPaneInfo_CentrePane, 2573).
--define(wxAuiPaneInfo_CloseButton, 2574).
--define(wxAuiPaneInfo_DefaultPane, 2575).
--define(wxAuiPaneInfo_DestroyOnClose, 2576).
--define(wxAuiPaneInfo_Direction, 2577).
--define(wxAuiPaneInfo_Dock, 2578).
--define(wxAuiPaneInfo_Dockable, 2579).
--define(wxAuiPaneInfo_Fixed, 2580).
--define(wxAuiPaneInfo_Float, 2581).
--define(wxAuiPaneInfo_Floatable, 2582).
--define(wxAuiPaneInfo_FloatingPosition_1, 2583).
--define(wxAuiPaneInfo_FloatingPosition_2, 2584).
--define(wxAuiPaneInfo_FloatingSize_1, 2585).
--define(wxAuiPaneInfo_FloatingSize_2, 2586).
--define(wxAuiPaneInfo_Gripper, 2587).
--define(wxAuiPaneInfo_GripperTop, 2588).
--define(wxAuiPaneInfo_HasBorder, 2589).
--define(wxAuiPaneInfo_HasCaption, 2590).
--define(wxAuiPaneInfo_HasCloseButton, 2591).
--define(wxAuiPaneInfo_HasFlag, 2592).
--define(wxAuiPaneInfo_HasGripper, 2593).
--define(wxAuiPaneInfo_HasGripperTop, 2594).
--define(wxAuiPaneInfo_HasMaximizeButton, 2595).
--define(wxAuiPaneInfo_HasMinimizeButton, 2596).
--define(wxAuiPaneInfo_HasPinButton, 2597).
--define(wxAuiPaneInfo_Hide, 2598).
--define(wxAuiPaneInfo_IsBottomDockable, 2599).
--define(wxAuiPaneInfo_IsDocked, 2600).
--define(wxAuiPaneInfo_IsFixed, 2601).
--define(wxAuiPaneInfo_IsFloatable, 2602).
--define(wxAuiPaneInfo_IsFloating, 2603).
--define(wxAuiPaneInfo_IsLeftDockable, 2604).
--define(wxAuiPaneInfo_IsMovable, 2605).
--define(wxAuiPaneInfo_IsOk, 2606).
--define(wxAuiPaneInfo_IsResizable, 2607).
--define(wxAuiPaneInfo_IsRightDockable, 2608).
--define(wxAuiPaneInfo_IsShown, 2609).
--define(wxAuiPaneInfo_IsToolbar, 2610).
--define(wxAuiPaneInfo_IsTopDockable, 2611).
--define(wxAuiPaneInfo_Layer, 2612).
--define(wxAuiPaneInfo_Left, 2613).
--define(wxAuiPaneInfo_LeftDockable, 2614).
--define(wxAuiPaneInfo_MaxSize_1, 2615).
--define(wxAuiPaneInfo_MaxSize_2, 2616).
--define(wxAuiPaneInfo_MaximizeButton, 2617).
--define(wxAuiPaneInfo_MinSize_1, 2618).
--define(wxAuiPaneInfo_MinSize_2, 2619).
--define(wxAuiPaneInfo_MinimizeButton, 2620).
--define(wxAuiPaneInfo_Movable, 2621).
--define(wxAuiPaneInfo_Name, 2622).
--define(wxAuiPaneInfo_PaneBorder, 2623).
--define(wxAuiPaneInfo_PinButton, 2624).
--define(wxAuiPaneInfo_Position, 2625).
--define(wxAuiPaneInfo_Resizable, 2626).
--define(wxAuiPaneInfo_Right, 2627).
--define(wxAuiPaneInfo_RightDockable, 2628).
--define(wxAuiPaneInfo_Row, 2629).
--define(wxAuiPaneInfo_SafeSet, 2630).
--define(wxAuiPaneInfo_SetFlag, 2631).
--define(wxAuiPaneInfo_Show, 2632).
--define(wxAuiPaneInfo_ToolbarPane, 2633).
--define(wxAuiPaneInfo_Top, 2634).
--define(wxAuiPaneInfo_TopDockable, 2635).
--define(wxAuiPaneInfo_Window, 2636).
--define(wxAuiNotebook_new_0, 2637).
--define(wxAuiNotebook_new_2, 2638).
--define(wxAuiNotebook_AddPage, 2639).
--define(wxAuiNotebook_Create, 2640).
--define(wxAuiNotebook_DeletePage, 2641).
--define(wxAuiNotebook_GetArtProvider, 2642).
--define(wxAuiNotebook_GetPage, 2643).
--define(wxAuiNotebook_GetPageBitmap, 2644).
--define(wxAuiNotebook_GetPageCount, 2645).
--define(wxAuiNotebook_GetPageIndex, 2646).
--define(wxAuiNotebook_GetPageText, 2647).
--define(wxAuiNotebook_GetSelection, 2648).
--define(wxAuiNotebook_InsertPage, 2649).
--define(wxAuiNotebook_RemovePage, 2650).
--define(wxAuiNotebook_SetArtProvider, 2651).
--define(wxAuiNotebook_SetFont, 2652).
--define(wxAuiNotebook_SetPageBitmap, 2653).
--define(wxAuiNotebook_SetPageText, 2654).
--define(wxAuiNotebook_SetSelection, 2655).
--define(wxAuiNotebook_SetTabCtrlHeight, 2656).
--define(wxAuiNotebook_SetUniformBitmapSize, 2657).
--define(wxAuiNotebook_destroy, 2658).
--define(wxMDIParentFrame_new_0, 2659).
--define(wxMDIParentFrame_new_4, 2660).
--define(wxMDIParentFrame_destruct, 2661).
--define(wxMDIParentFrame_ActivateNext, 2662).
--define(wxMDIParentFrame_ActivatePrevious, 2663).
--define(wxMDIParentFrame_ArrangeIcons, 2664).
--define(wxMDIParentFrame_Cascade, 2665).
--define(wxMDIParentFrame_Create, 2666).
--define(wxMDIParentFrame_GetActiveChild, 2667).
--define(wxMDIParentFrame_GetClientWindow, 2668).
--define(wxMDIParentFrame_Tile, 2669).
--define(wxMDIChildFrame_new_0, 2670).
--define(wxMDIChildFrame_new_4, 2671).
--define(wxMDIChildFrame_destruct, 2672).
--define(wxMDIChildFrame_Activate, 2673).
--define(wxMDIChildFrame_Create, 2674).
--define(wxMDIChildFrame_Maximize, 2675).
--define(wxMDIChildFrame_Restore, 2676).
--define(wxMDIClientWindow_new_0, 2677).
--define(wxMDIClientWindow_new_2, 2678).
--define(wxMDIClientWindow_destruct, 2679).
--define(wxMDIClientWindow_CreateClient, 2680).
--define(wxLayoutAlgorithm_new, 2681).
--define(wxLayoutAlgorithm_LayoutFrame, 2682).
--define(wxLayoutAlgorithm_LayoutMDIFrame, 2683).
--define(wxLayoutAlgorithm_LayoutWindow, 2684).
--define(wxLayoutAlgorithm_destroy, 2685).
--define(wxEvent_GetId, 2686).
--define(wxEvent_GetSkipped, 2687).
--define(wxEvent_GetTimestamp, 2688).
--define(wxEvent_IsCommandEvent, 2689).
--define(wxEvent_ResumePropagation, 2690).
--define(wxEvent_ShouldPropagate, 2691).
--define(wxEvent_Skip, 2692).
--define(wxEvent_StopPropagation, 2693).
--define(wxCommandEvent_getClientData, 2694).
--define(wxCommandEvent_GetExtraLong, 2695).
--define(wxCommandEvent_GetInt, 2696).
--define(wxCommandEvent_GetSelection, 2697).
--define(wxCommandEvent_GetString, 2698).
--define(wxCommandEvent_IsChecked, 2699).
--define(wxCommandEvent_IsSelection, 2700).
--define(wxCommandEvent_SetInt, 2701).
--define(wxCommandEvent_SetString, 2702).
--define(wxScrollEvent_GetOrientation, 2703).
--define(wxScrollEvent_GetPosition, 2704).
--define(wxScrollWinEvent_GetOrientation, 2705).
--define(wxScrollWinEvent_GetPosition, 2706).
--define(wxMouseEvent_AltDown, 2707).
--define(wxMouseEvent_Button, 2708).
--define(wxMouseEvent_ButtonDClick, 2709).
--define(wxMouseEvent_ButtonDown, 2710).
--define(wxMouseEvent_ButtonUp, 2711).
--define(wxMouseEvent_CmdDown, 2712).
--define(wxMouseEvent_ControlDown, 2713).
--define(wxMouseEvent_Dragging, 2714).
--define(wxMouseEvent_Entering, 2715).
--define(wxMouseEvent_GetButton, 2716).
--define(wxMouseEvent_GetPosition, 2719).
--define(wxMouseEvent_GetLogicalPosition, 2720).
--define(wxMouseEvent_GetLinesPerAction, 2721).
--define(wxMouseEvent_GetWheelRotation, 2722).
--define(wxMouseEvent_GetWheelDelta, 2723).
--define(wxMouseEvent_GetX, 2724).
--define(wxMouseEvent_GetY, 2725).
--define(wxMouseEvent_IsButton, 2726).
--define(wxMouseEvent_IsPageScroll, 2727).
--define(wxMouseEvent_Leaving, 2728).
--define(wxMouseEvent_LeftDClick, 2729).
--define(wxMouseEvent_LeftDown, 2730).
--define(wxMouseEvent_LeftIsDown, 2731).
--define(wxMouseEvent_LeftUp, 2732).
--define(wxMouseEvent_MetaDown, 2733).
--define(wxMouseEvent_MiddleDClick, 2734).
--define(wxMouseEvent_MiddleDown, 2735).
--define(wxMouseEvent_MiddleIsDown, 2736).
--define(wxMouseEvent_MiddleUp, 2737).
--define(wxMouseEvent_Moving, 2738).
--define(wxMouseEvent_RightDClick, 2739).
--define(wxMouseEvent_RightDown, 2740).
--define(wxMouseEvent_RightIsDown, 2741).
--define(wxMouseEvent_RightUp, 2742).
--define(wxMouseEvent_ShiftDown, 2743).
--define(wxSetCursorEvent_GetCursor, 2744).
--define(wxSetCursorEvent_GetX, 2745).
--define(wxSetCursorEvent_GetY, 2746).
--define(wxSetCursorEvent_HasCursor, 2747).
--define(wxSetCursorEvent_SetCursor, 2748).
--define(wxKeyEvent_AltDown, 2749).
--define(wxKeyEvent_CmdDown, 2750).
--define(wxKeyEvent_ControlDown, 2751).
--define(wxKeyEvent_GetKeyCode, 2752).
--define(wxKeyEvent_GetModifiers, 2753).
--define(wxKeyEvent_GetPosition, 2756).
--define(wxKeyEvent_GetRawKeyCode, 2757).
--define(wxKeyEvent_GetRawKeyFlags, 2758).
--define(wxKeyEvent_GetUnicodeKey, 2759).
--define(wxKeyEvent_GetX, 2760).
--define(wxKeyEvent_GetY, 2761).
--define(wxKeyEvent_HasModifiers, 2762).
--define(wxKeyEvent_MetaDown, 2763).
--define(wxKeyEvent_ShiftDown, 2764).
--define(wxSizeEvent_GetSize, 2765).
--define(wxMoveEvent_GetPosition, 2766).
--define(wxEraseEvent_GetDC, 2767).
--define(wxFocusEvent_GetWindow, 2768).
--define(wxChildFocusEvent_GetWindow, 2769).
--define(wxMenuEvent_GetMenu, 2770).
--define(wxMenuEvent_GetMenuId, 2771).
--define(wxMenuEvent_IsPopup, 2772).
--define(wxCloseEvent_CanVeto, 2773).
--define(wxCloseEvent_GetLoggingOff, 2774).
--define(wxCloseEvent_SetCanVeto, 2775).
--define(wxCloseEvent_SetLoggingOff, 2776).
--define(wxCloseEvent_Veto, 2777).
--define(wxShowEvent_SetShow, 2778).
--define(wxShowEvent_GetShow, 2779).
--define(wxIconizeEvent_Iconized, 2780).
--define(wxJoystickEvent_ButtonDown, 2781).
--define(wxJoystickEvent_ButtonIsDown, 2782).
--define(wxJoystickEvent_ButtonUp, 2783).
--define(wxJoystickEvent_GetButtonChange, 2784).
--define(wxJoystickEvent_GetButtonState, 2785).
--define(wxJoystickEvent_GetJoystick, 2786).
--define(wxJoystickEvent_GetPosition, 2787).
--define(wxJoystickEvent_GetZPosition, 2788).
--define(wxJoystickEvent_IsButton, 2789).
--define(wxJoystickEvent_IsMove, 2790).
--define(wxJoystickEvent_IsZMove, 2791).
--define(wxUpdateUIEvent_CanUpdate, 2792).
--define(wxUpdateUIEvent_Check, 2793).
--define(wxUpdateUIEvent_Enable, 2794).
--define(wxUpdateUIEvent_Show, 2795).
--define(wxUpdateUIEvent_GetChecked, 2796).
--define(wxUpdateUIEvent_GetEnabled, 2797).
--define(wxUpdateUIEvent_GetShown, 2798).
--define(wxUpdateUIEvent_GetSetChecked, 2799).
--define(wxUpdateUIEvent_GetSetEnabled, 2800).
--define(wxUpdateUIEvent_GetSetShown, 2801).
--define(wxUpdateUIEvent_GetSetText, 2802).
--define(wxUpdateUIEvent_GetText, 2803).
--define(wxUpdateUIEvent_GetMode, 2804).
--define(wxUpdateUIEvent_GetUpdateInterval, 2805).
--define(wxUpdateUIEvent_ResetUpdateTime, 2806).
--define(wxUpdateUIEvent_SetMode, 2807).
--define(wxUpdateUIEvent_SetText, 2808).
--define(wxUpdateUIEvent_SetUpdateInterval, 2809).
--define(wxMouseCaptureChangedEvent_GetCapturedWindow, 2810).
--define(wxPaletteChangedEvent_SetChangedWindow, 2811).
--define(wxPaletteChangedEvent_GetChangedWindow, 2812).
--define(wxQueryNewPaletteEvent_SetPaletteRealized, 2813).
--define(wxQueryNewPaletteEvent_GetPaletteRealized, 2814).
--define(wxNavigationKeyEvent_GetDirection, 2815).
--define(wxNavigationKeyEvent_SetDirection, 2816).
--define(wxNavigationKeyEvent_IsWindowChange, 2817).
--define(wxNavigationKeyEvent_SetWindowChange, 2818).
--define(wxNavigationKeyEvent_IsFromTab, 2819).
--define(wxNavigationKeyEvent_SetFromTab, 2820).
--define(wxNavigationKeyEvent_GetCurrentFocus, 2821).
--define(wxNavigationKeyEvent_SetCurrentFocus, 2822).
--define(wxHelpEvent_GetOrigin, 2823).
--define(wxHelpEvent_GetPosition, 2824).
--define(wxHelpEvent_SetOrigin, 2825).
--define(wxHelpEvent_SetPosition, 2826).
--define(wxContextMenuEvent_GetPosition, 2827).
--define(wxContextMenuEvent_SetPosition, 2828).
--define(wxIdleEvent_CanSend, 2829).
--define(wxIdleEvent_GetMode, 2830).
--define(wxIdleEvent_RequestMore, 2831).
--define(wxIdleEvent_MoreRequested, 2832).
--define(wxIdleEvent_SetMode, 2833).
--define(wxGridEvent_AltDown, 2834).
--define(wxGridEvent_ControlDown, 2835).
--define(wxGridEvent_GetCol, 2836).
--define(wxGridEvent_GetPosition, 2837).
--define(wxGridEvent_GetRow, 2838).
--define(wxGridEvent_MetaDown, 2839).
--define(wxGridEvent_Selecting, 2840).
--define(wxGridEvent_ShiftDown, 2841).
--define(wxNotifyEvent_Allow, 2842).
--define(wxNotifyEvent_IsAllowed, 2843).
--define(wxNotifyEvent_Veto, 2844).
--define(wxSashEvent_GetEdge, 2845).
--define(wxSashEvent_GetDragRect, 2846).
--define(wxSashEvent_GetDragStatus, 2847).
--define(wxListEvent_GetCacheFrom, 2848).
--define(wxListEvent_GetCacheTo, 2849).
--define(wxListEvent_GetKeyCode, 2850).
--define(wxListEvent_GetIndex, 2851).
--define(wxListEvent_GetColumn, 2852).
--define(wxListEvent_GetPoint, 2853).
--define(wxListEvent_GetLabel, 2854).
--define(wxListEvent_GetText, 2855).
--define(wxListEvent_GetImage, 2856).
--define(wxListEvent_GetData, 2857).
--define(wxListEvent_GetMask, 2858).
--define(wxListEvent_GetItem, 2859).
--define(wxListEvent_IsEditCancelled, 2860).
--define(wxDateEvent_GetDate, 2861).
--define(wxCalendarEvent_GetWeekDay, 2862).
--define(wxFileDirPickerEvent_GetPath, 2863).
--define(wxColourPickerEvent_GetColour, 2864).
--define(wxFontPickerEvent_GetFont, 2865).
--define(wxStyledTextEvent_GetPosition, 2866).
--define(wxStyledTextEvent_GetKey, 2867).
--define(wxStyledTextEvent_GetModifiers, 2868).
--define(wxStyledTextEvent_GetModificationType, 2869).
--define(wxStyledTextEvent_GetText, 2870).
--define(wxStyledTextEvent_GetLength, 2871).
--define(wxStyledTextEvent_GetLinesAdded, 2872).
--define(wxStyledTextEvent_GetLine, 2873).
--define(wxStyledTextEvent_GetFoldLevelNow, 2874).
--define(wxStyledTextEvent_GetFoldLevelPrev, 2875).
--define(wxStyledTextEvent_GetMargin, 2876).
--define(wxStyledTextEvent_GetMessage, 2877).
--define(wxStyledTextEvent_GetWParam, 2878).
--define(wxStyledTextEvent_GetLParam, 2879).
--define(wxStyledTextEvent_GetListType, 2880).
--define(wxStyledTextEvent_GetX, 2881).
--define(wxStyledTextEvent_GetY, 2882).
--define(wxStyledTextEvent_GetDragText, 2883).
--define(wxStyledTextEvent_GetDragAllowMove, 2884).
--define(wxStyledTextEvent_GetDragResult, 2885).
--define(wxStyledTextEvent_GetShift, 2886).
--define(wxStyledTextEvent_GetControl, 2887).
--define(wxStyledTextEvent_GetAlt, 2888).
--define(utils_wxGetKeyState, 2889).
--define(utils_wxGetMousePosition, 2890).
--define(utils_wxGetMouseState, 2891).
--define(utils_wxSetDetectableAutoRepeat, 2892).
--define(utils_wxBell, 2893).
--define(utils_wxFindMenuItemId, 2894).
--define(utils_wxGenericFindWindowAtPoint, 2895).
--define(utils_wxFindWindowAtPoint, 2896).
--define(utils_wxBeginBusyCursor, 2897).
--define(utils_wxEndBusyCursor, 2898).
--define(utils_wxIsBusy, 2899).
--define(utils_wxShutdown, 2900).
--define(utils_wxShell, 2901).
--define(utils_wxLaunchDefaultBrowser, 2902).
--define(utils_wxGetEmailAddress, 2903).
--define(utils_wxGetUserId, 2904).
--define(utils_wxGetHomeDir, 2905).
--define(utils_wxNewId, 2906).
--define(utils_wxRegisterId, 2907).
--define(utils_wxGetCurrentId, 2908).
--define(utils_wxGetOsDescription, 2909).
--define(utils_wxIsPlatformLittleEndian, 2910).
--define(utils_wxIsPlatform64Bit, 2911).
--define(wxPrintout_new, 2912).
--define(wxPrintout_destruct, 2913).
--define(wxPrintout_GetDC, 2914).
--define(wxPrintout_GetPageSizeMM, 2915).
--define(wxPrintout_GetPageSizePixels, 2916).
--define(wxPrintout_GetPaperRectPixels, 2917).
--define(wxPrintout_GetPPIPrinter, 2918).
--define(wxPrintout_GetPPIScreen, 2919).
--define(wxPrintout_GetTitle, 2920).
--define(wxPrintout_IsPreview, 2921).
--define(wxPrintout_FitThisSizeToPaper, 2922).
--define(wxPrintout_FitThisSizeToPage, 2923).
--define(wxPrintout_FitThisSizeToPageMargins, 2924).
--define(wxPrintout_MapScreenSizeToPaper, 2925).
--define(wxPrintout_MapScreenSizeToPage, 2926).
--define(wxPrintout_MapScreenSizeToPageMargins, 2927).
--define(wxPrintout_MapScreenSizeToDevice, 2928).
--define(wxPrintout_GetLogicalPaperRect, 2929).
--define(wxPrintout_GetLogicalPageRect, 2930).
--define(wxPrintout_GetLogicalPageMarginsRect, 2931).
--define(wxPrintout_SetLogicalOrigin, 2932).
--define(wxPrintout_OffsetLogicalOrigin, 2933).
--define(wxStyledTextCtrl_new_2, 2934).
--define(wxStyledTextCtrl_new_0, 2935).
--define(wxStyledTextCtrl_destruct, 2936).
--define(wxStyledTextCtrl_Create, 2937).
--define(wxStyledTextCtrl_AddText, 2938).
--define(wxStyledTextCtrl_AddStyledText, 2939).
--define(wxStyledTextCtrl_InsertText, 2940).
--define(wxStyledTextCtrl_ClearAll, 2941).
--define(wxStyledTextCtrl_ClearDocumentStyle, 2942).
--define(wxStyledTextCtrl_GetLength, 2943).
--define(wxStyledTextCtrl_GetCharAt, 2944).
--define(wxStyledTextCtrl_GetCurrentPos, 2945).
--define(wxStyledTextCtrl_GetAnchor, 2946).
--define(wxStyledTextCtrl_GetStyleAt, 2947).
--define(wxStyledTextCtrl_Redo, 2948).
--define(wxStyledTextCtrl_SetUndoCollection, 2949).
--define(wxStyledTextCtrl_SelectAll, 2950).
--define(wxStyledTextCtrl_SetSavePoint, 2951).
--define(wxStyledTextCtrl_GetStyledText, 2952).
--define(wxStyledTextCtrl_CanRedo, 2953).
--define(wxStyledTextCtrl_MarkerLineFromHandle, 2954).
--define(wxStyledTextCtrl_MarkerDeleteHandle, 2955).
--define(wxStyledTextCtrl_GetUndoCollection, 2956).
--define(wxStyledTextCtrl_GetViewWhiteSpace, 2957).
--define(wxStyledTextCtrl_SetViewWhiteSpace, 2958).
--define(wxStyledTextCtrl_PositionFromPoint, 2959).
--define(wxStyledTextCtrl_PositionFromPointClose, 2960).
--define(wxStyledTextCtrl_GotoLine, 2961).
--define(wxStyledTextCtrl_GotoPos, 2962).
--define(wxStyledTextCtrl_SetAnchor, 2963).
--define(wxStyledTextCtrl_GetCurLine, 2964).
--define(wxStyledTextCtrl_GetEndStyled, 2965).
--define(wxStyledTextCtrl_ConvertEOLs, 2966).
--define(wxStyledTextCtrl_GetEOLMode, 2967).
--define(wxStyledTextCtrl_SetEOLMode, 2968).
--define(wxStyledTextCtrl_StartStyling, 2969).
--define(wxStyledTextCtrl_SetStyling, 2970).
--define(wxStyledTextCtrl_GetBufferedDraw, 2971).
--define(wxStyledTextCtrl_SetBufferedDraw, 2972).
--define(wxStyledTextCtrl_SetTabWidth, 2973).
--define(wxStyledTextCtrl_GetTabWidth, 2974).
--define(wxStyledTextCtrl_SetCodePage, 2975).
--define(wxStyledTextCtrl_MarkerDefine, 2976).
--define(wxStyledTextCtrl_MarkerSetForeground, 2977).
--define(wxStyledTextCtrl_MarkerSetBackground, 2978).
--define(wxStyledTextCtrl_MarkerAdd, 2979).
--define(wxStyledTextCtrl_MarkerDelete, 2980).
--define(wxStyledTextCtrl_MarkerDeleteAll, 2981).
--define(wxStyledTextCtrl_MarkerGet, 2982).
--define(wxStyledTextCtrl_MarkerNext, 2983).
--define(wxStyledTextCtrl_MarkerPrevious, 2984).
--define(wxStyledTextCtrl_MarkerDefineBitmap, 2985).
--define(wxStyledTextCtrl_MarkerAddSet, 2986).
--define(wxStyledTextCtrl_MarkerSetAlpha, 2987).
--define(wxStyledTextCtrl_SetMarginType, 2988).
--define(wxStyledTextCtrl_GetMarginType, 2989).
--define(wxStyledTextCtrl_SetMarginWidth, 2990).
--define(wxStyledTextCtrl_GetMarginWidth, 2991).
--define(wxStyledTextCtrl_SetMarginMask, 2992).
--define(wxStyledTextCtrl_GetMarginMask, 2993).
--define(wxStyledTextCtrl_SetMarginSensitive, 2994).
--define(wxStyledTextCtrl_GetMarginSensitive, 2995).
--define(wxStyledTextCtrl_StyleClearAll, 2996).
--define(wxStyledTextCtrl_StyleSetForeground, 2997).
--define(wxStyledTextCtrl_StyleSetBackground, 2998).
--define(wxStyledTextCtrl_StyleSetBold, 2999).
--define(wxStyledTextCtrl_StyleSetItalic, 3000).
--define(wxStyledTextCtrl_StyleSetSize, 3001).
--define(wxStyledTextCtrl_StyleSetFaceName, 3002).
--define(wxStyledTextCtrl_StyleSetEOLFilled, 3003).
--define(wxStyledTextCtrl_StyleResetDefault, 3004).
--define(wxStyledTextCtrl_StyleSetUnderline, 3005).
--define(wxStyledTextCtrl_StyleSetCase, 3006).
--define(wxStyledTextCtrl_StyleSetHotSpot, 3007).
--define(wxStyledTextCtrl_SetSelForeground, 3008).
--define(wxStyledTextCtrl_SetSelBackground, 3009).
--define(wxStyledTextCtrl_GetSelAlpha, 3010).
--define(wxStyledTextCtrl_SetSelAlpha, 3011).
--define(wxStyledTextCtrl_SetCaretForeground, 3012).
--define(wxStyledTextCtrl_CmdKeyAssign, 3013).
--define(wxStyledTextCtrl_CmdKeyClear, 3014).
--define(wxStyledTextCtrl_CmdKeyClearAll, 3015).
--define(wxStyledTextCtrl_SetStyleBytes, 3016).
--define(wxStyledTextCtrl_StyleSetVisible, 3017).
--define(wxStyledTextCtrl_GetCaretPeriod, 3018).
--define(wxStyledTextCtrl_SetCaretPeriod, 3019).
--define(wxStyledTextCtrl_SetWordChars, 3020).
--define(wxStyledTextCtrl_BeginUndoAction, 3021).
--define(wxStyledTextCtrl_EndUndoAction, 3022).
--define(wxStyledTextCtrl_IndicatorSetStyle, 3023).
--define(wxStyledTextCtrl_IndicatorGetStyle, 3024).
--define(wxStyledTextCtrl_IndicatorSetForeground, 3025).
--define(wxStyledTextCtrl_IndicatorGetForeground, 3026).
--define(wxStyledTextCtrl_SetWhitespaceForeground, 3027).
--define(wxStyledTextCtrl_SetWhitespaceBackground, 3028).
--define(wxStyledTextCtrl_GetStyleBits, 3029).
--define(wxStyledTextCtrl_SetLineState, 3030).
--define(wxStyledTextCtrl_GetLineState, 3031).
--define(wxStyledTextCtrl_GetMaxLineState, 3032).
--define(wxStyledTextCtrl_GetCaretLineVisible, 3033).
--define(wxStyledTextCtrl_SetCaretLineVisible, 3034).
--define(wxStyledTextCtrl_GetCaretLineBackground, 3035).
--define(wxStyledTextCtrl_SetCaretLineBackground, 3036).
--define(wxStyledTextCtrl_AutoCompShow, 3037).
--define(wxStyledTextCtrl_AutoCompCancel, 3038).
--define(wxStyledTextCtrl_AutoCompActive, 3039).
--define(wxStyledTextCtrl_AutoCompPosStart, 3040).
--define(wxStyledTextCtrl_AutoCompComplete, 3041).
--define(wxStyledTextCtrl_AutoCompStops, 3042).
--define(wxStyledTextCtrl_AutoCompSetSeparator, 3043).
--define(wxStyledTextCtrl_AutoCompGetSeparator, 3044).
--define(wxStyledTextCtrl_AutoCompSelect, 3045).
--define(wxStyledTextCtrl_AutoCompSetCancelAtStart, 3046).
--define(wxStyledTextCtrl_AutoCompGetCancelAtStart, 3047).
--define(wxStyledTextCtrl_AutoCompSetFillUps, 3048).
--define(wxStyledTextCtrl_AutoCompSetChooseSingle, 3049).
--define(wxStyledTextCtrl_AutoCompGetChooseSingle, 3050).
--define(wxStyledTextCtrl_AutoCompSetIgnoreCase, 3051).
--define(wxStyledTextCtrl_AutoCompGetIgnoreCase, 3052).
--define(wxStyledTextCtrl_UserListShow, 3053).
--define(wxStyledTextCtrl_AutoCompSetAutoHide, 3054).
--define(wxStyledTextCtrl_AutoCompGetAutoHide, 3055).
--define(wxStyledTextCtrl_AutoCompSetDropRestOfWord, 3056).
--define(wxStyledTextCtrl_AutoCompGetDropRestOfWord, 3057).
--define(wxStyledTextCtrl_RegisterImage, 3058).
--define(wxStyledTextCtrl_ClearRegisteredImages, 3059).
--define(wxStyledTextCtrl_AutoCompGetTypeSeparator, 3060).
--define(wxStyledTextCtrl_AutoCompSetTypeSeparator, 3061).
--define(wxStyledTextCtrl_AutoCompSetMaxWidth, 3062).
--define(wxStyledTextCtrl_AutoCompGetMaxWidth, 3063).
--define(wxStyledTextCtrl_AutoCompSetMaxHeight, 3064).
--define(wxStyledTextCtrl_AutoCompGetMaxHeight, 3065).
--define(wxStyledTextCtrl_SetIndent, 3066).
--define(wxStyledTextCtrl_GetIndent, 3067).
--define(wxStyledTextCtrl_SetUseTabs, 3068).
--define(wxStyledTextCtrl_GetUseTabs, 3069).
--define(wxStyledTextCtrl_SetLineIndentation, 3070).
--define(wxStyledTextCtrl_GetLineIndentation, 3071).
--define(wxStyledTextCtrl_GetLineIndentPosition, 3072).
--define(wxStyledTextCtrl_GetColumn, 3073).
--define(wxStyledTextCtrl_SetUseHorizontalScrollBar, 3074).
--define(wxStyledTextCtrl_GetUseHorizontalScrollBar, 3075).
--define(wxStyledTextCtrl_SetIndentationGuides, 3076).
--define(wxStyledTextCtrl_GetIndentationGuides, 3077).
--define(wxStyledTextCtrl_SetHighlightGuide, 3078).
--define(wxStyledTextCtrl_GetHighlightGuide, 3079).
--define(wxStyledTextCtrl_GetLineEndPosition, 3080).
--define(wxStyledTextCtrl_GetCodePage, 3081).
--define(wxStyledTextCtrl_GetCaretForeground, 3082).
--define(wxStyledTextCtrl_GetReadOnly, 3083).
--define(wxStyledTextCtrl_SetCurrentPos, 3084).
--define(wxStyledTextCtrl_SetSelectionStart, 3085).
--define(wxStyledTextCtrl_GetSelectionStart, 3086).
--define(wxStyledTextCtrl_SetSelectionEnd, 3087).
--define(wxStyledTextCtrl_GetSelectionEnd, 3088).
--define(wxStyledTextCtrl_SetPrintMagnification, 3089).
--define(wxStyledTextCtrl_GetPrintMagnification, 3090).
--define(wxStyledTextCtrl_SetPrintColourMode, 3091).
--define(wxStyledTextCtrl_GetPrintColourMode, 3092).
--define(wxStyledTextCtrl_FindText, 3093).
--define(wxStyledTextCtrl_FormatRange, 3094).
--define(wxStyledTextCtrl_GetFirstVisibleLine, 3095).
--define(wxStyledTextCtrl_GetLine, 3096).
--define(wxStyledTextCtrl_GetLineCount, 3097).
--define(wxStyledTextCtrl_SetMarginLeft, 3098).
--define(wxStyledTextCtrl_GetMarginLeft, 3099).
--define(wxStyledTextCtrl_SetMarginRight, 3100).
--define(wxStyledTextCtrl_GetMarginRight, 3101).
--define(wxStyledTextCtrl_GetModify, 3102).
--define(wxStyledTextCtrl_SetSelection, 3103).
--define(wxStyledTextCtrl_GetSelectedText, 3104).
--define(wxStyledTextCtrl_GetTextRange, 3105).
--define(wxStyledTextCtrl_HideSelection, 3106).
--define(wxStyledTextCtrl_LineFromPosition, 3107).
--define(wxStyledTextCtrl_PositionFromLine, 3108).
--define(wxStyledTextCtrl_LineScroll, 3109).
--define(wxStyledTextCtrl_EnsureCaretVisible, 3110).
--define(wxStyledTextCtrl_ReplaceSelection, 3111).
--define(wxStyledTextCtrl_SetReadOnly, 3112).
--define(wxStyledTextCtrl_CanPaste, 3113).
--define(wxStyledTextCtrl_CanUndo, 3114).
--define(wxStyledTextCtrl_EmptyUndoBuffer, 3115).
--define(wxStyledTextCtrl_Undo, 3116).
--define(wxStyledTextCtrl_Cut, 3117).
--define(wxStyledTextCtrl_Copy, 3118).
--define(wxStyledTextCtrl_Paste, 3119).
--define(wxStyledTextCtrl_Clear, 3120).
--define(wxStyledTextCtrl_SetText, 3121).
--define(wxStyledTextCtrl_GetText, 3122).
--define(wxStyledTextCtrl_GetTextLength, 3123).
--define(wxStyledTextCtrl_GetOvertype, 3124).
--define(wxStyledTextCtrl_SetCaretWidth, 3125).
--define(wxStyledTextCtrl_GetCaretWidth, 3126).
--define(wxStyledTextCtrl_SetTargetStart, 3127).
--define(wxStyledTextCtrl_GetTargetStart, 3128).
--define(wxStyledTextCtrl_SetTargetEnd, 3129).
--define(wxStyledTextCtrl_GetTargetEnd, 3130).
--define(wxStyledTextCtrl_ReplaceTarget, 3131).
--define(wxStyledTextCtrl_SearchInTarget, 3132).
--define(wxStyledTextCtrl_SetSearchFlags, 3133).
--define(wxStyledTextCtrl_GetSearchFlags, 3134).
--define(wxStyledTextCtrl_CallTipShow, 3135).
--define(wxStyledTextCtrl_CallTipCancel, 3136).
--define(wxStyledTextCtrl_CallTipActive, 3137).
--define(wxStyledTextCtrl_CallTipPosAtStart, 3138).
--define(wxStyledTextCtrl_CallTipSetHighlight, 3139).
--define(wxStyledTextCtrl_CallTipSetBackground, 3140).
--define(wxStyledTextCtrl_CallTipSetForeground, 3141).
--define(wxStyledTextCtrl_CallTipSetForegroundHighlight, 3142).
--define(wxStyledTextCtrl_CallTipUseStyle, 3143).
--define(wxStyledTextCtrl_VisibleFromDocLine, 3144).
--define(wxStyledTextCtrl_DocLineFromVisible, 3145).
--define(wxStyledTextCtrl_WrapCount, 3146).
--define(wxStyledTextCtrl_SetFoldLevel, 3147).
--define(wxStyledTextCtrl_GetFoldLevel, 3148).
--define(wxStyledTextCtrl_GetLastChild, 3149).
--define(wxStyledTextCtrl_GetFoldParent, 3150).
--define(wxStyledTextCtrl_ShowLines, 3151).
--define(wxStyledTextCtrl_HideLines, 3152).
--define(wxStyledTextCtrl_GetLineVisible, 3153).
--define(wxStyledTextCtrl_SetFoldExpanded, 3154).
--define(wxStyledTextCtrl_GetFoldExpanded, 3155).
--define(wxStyledTextCtrl_ToggleFold, 3156).
--define(wxStyledTextCtrl_EnsureVisible, 3157).
--define(wxStyledTextCtrl_SetFoldFlags, 3158).
--define(wxStyledTextCtrl_EnsureVisibleEnforcePolicy, 3159).
--define(wxStyledTextCtrl_SetTabIndents, 3160).
--define(wxStyledTextCtrl_GetTabIndents, 3161).
--define(wxStyledTextCtrl_SetBackSpaceUnIndents, 3162).
--define(wxStyledTextCtrl_GetBackSpaceUnIndents, 3163).
--define(wxStyledTextCtrl_SetMouseDwellTime, 3164).
--define(wxStyledTextCtrl_GetMouseDwellTime, 3165).
--define(wxStyledTextCtrl_WordStartPosition, 3166).
--define(wxStyledTextCtrl_WordEndPosition, 3167).
--define(wxStyledTextCtrl_SetWrapMode, 3168).
--define(wxStyledTextCtrl_GetWrapMode, 3169).
--define(wxStyledTextCtrl_SetWrapVisualFlags, 3170).
--define(wxStyledTextCtrl_GetWrapVisualFlags, 3171).
--define(wxStyledTextCtrl_SetWrapVisualFlagsLocation, 3172).
--define(wxStyledTextCtrl_GetWrapVisualFlagsLocation, 3173).
--define(wxStyledTextCtrl_SetWrapStartIndent, 3174).
--define(wxStyledTextCtrl_GetWrapStartIndent, 3175).
--define(wxStyledTextCtrl_SetLayoutCache, 3176).
--define(wxStyledTextCtrl_GetLayoutCache, 3177).
--define(wxStyledTextCtrl_SetScrollWidth, 3178).
--define(wxStyledTextCtrl_GetScrollWidth, 3179).
--define(wxStyledTextCtrl_TextWidth, 3180).
--define(wxStyledTextCtrl_GetEndAtLastLine, 3181).
--define(wxStyledTextCtrl_TextHeight, 3182).
--define(wxStyledTextCtrl_SetUseVerticalScrollBar, 3183).
--define(wxStyledTextCtrl_GetUseVerticalScrollBar, 3184).
--define(wxStyledTextCtrl_AppendText, 3185).
--define(wxStyledTextCtrl_GetTwoPhaseDraw, 3186).
--define(wxStyledTextCtrl_SetTwoPhaseDraw, 3187).
--define(wxStyledTextCtrl_TargetFromSelection, 3188).
--define(wxStyledTextCtrl_LinesJoin, 3189).
--define(wxStyledTextCtrl_LinesSplit, 3190).
--define(wxStyledTextCtrl_SetFoldMarginColour, 3191).
--define(wxStyledTextCtrl_SetFoldMarginHiColour, 3192).
--define(wxStyledTextCtrl_LineDown, 3193).
--define(wxStyledTextCtrl_LineDownExtend, 3194).
--define(wxStyledTextCtrl_LineUp, 3195).
--define(wxStyledTextCtrl_LineUpExtend, 3196).
--define(wxStyledTextCtrl_CharLeft, 3197).
--define(wxStyledTextCtrl_CharLeftExtend, 3198).
--define(wxStyledTextCtrl_CharRight, 3199).
--define(wxStyledTextCtrl_CharRightExtend, 3200).
--define(wxStyledTextCtrl_WordLeft, 3201).
--define(wxStyledTextCtrl_WordLeftExtend, 3202).
--define(wxStyledTextCtrl_WordRight, 3203).
--define(wxStyledTextCtrl_WordRightExtend, 3204).
--define(wxStyledTextCtrl_Home, 3205).
--define(wxStyledTextCtrl_HomeExtend, 3206).
--define(wxStyledTextCtrl_LineEnd, 3207).
--define(wxStyledTextCtrl_LineEndExtend, 3208).
--define(wxStyledTextCtrl_DocumentStart, 3209).
--define(wxStyledTextCtrl_DocumentStartExtend, 3210).
--define(wxStyledTextCtrl_DocumentEnd, 3211).
--define(wxStyledTextCtrl_DocumentEndExtend, 3212).
--define(wxStyledTextCtrl_PageUp, 3213).
--define(wxStyledTextCtrl_PageUpExtend, 3214).
--define(wxStyledTextCtrl_PageDown, 3215).
--define(wxStyledTextCtrl_PageDownExtend, 3216).
--define(wxStyledTextCtrl_EditToggleOvertype, 3217).
--define(wxStyledTextCtrl_Cancel, 3218).
--define(wxStyledTextCtrl_DeleteBack, 3219).
--define(wxStyledTextCtrl_Tab, 3220).
--define(wxStyledTextCtrl_BackTab, 3221).
--define(wxStyledTextCtrl_NewLine, 3222).
--define(wxStyledTextCtrl_FormFeed, 3223).
--define(wxStyledTextCtrl_VCHome, 3224).
--define(wxStyledTextCtrl_VCHomeExtend, 3225).
--define(wxStyledTextCtrl_ZoomIn, 3226).
--define(wxStyledTextCtrl_ZoomOut, 3227).
--define(wxStyledTextCtrl_DelWordLeft, 3228).
--define(wxStyledTextCtrl_DelWordRight, 3229).
--define(wxStyledTextCtrl_LineCut, 3230).
--define(wxStyledTextCtrl_LineDelete, 3231).
--define(wxStyledTextCtrl_LineTranspose, 3232).
--define(wxStyledTextCtrl_LineDuplicate, 3233).
--define(wxStyledTextCtrl_LowerCase, 3234).
--define(wxStyledTextCtrl_UpperCase, 3235).
--define(wxStyledTextCtrl_LineScrollDown, 3236).
--define(wxStyledTextCtrl_LineScrollUp, 3237).
--define(wxStyledTextCtrl_DeleteBackNotLine, 3238).
--define(wxStyledTextCtrl_HomeDisplay, 3239).
--define(wxStyledTextCtrl_HomeDisplayExtend, 3240).
--define(wxStyledTextCtrl_LineEndDisplay, 3241).
--define(wxStyledTextCtrl_LineEndDisplayExtend, 3242).
--define(wxStyledTextCtrl_HomeWrapExtend, 3243).
--define(wxStyledTextCtrl_LineEndWrap, 3244).
--define(wxStyledTextCtrl_LineEndWrapExtend, 3245).
--define(wxStyledTextCtrl_VCHomeWrap, 3246).
--define(wxStyledTextCtrl_VCHomeWrapExtend, 3247).
--define(wxStyledTextCtrl_LineCopy, 3248).
--define(wxStyledTextCtrl_MoveCaretInsideView, 3249).
--define(wxStyledTextCtrl_LineLength, 3250).
--define(wxStyledTextCtrl_BraceHighlight, 3251).
--define(wxStyledTextCtrl_BraceBadLight, 3252).
--define(wxStyledTextCtrl_BraceMatch, 3253).
--define(wxStyledTextCtrl_GetViewEOL, 3254).
--define(wxStyledTextCtrl_SetViewEOL, 3255).
--define(wxStyledTextCtrl_SetModEventMask, 3256).
--define(wxStyledTextCtrl_GetEdgeColumn, 3257).
--define(wxStyledTextCtrl_SetEdgeColumn, 3258).
--define(wxStyledTextCtrl_GetEdgeMode, 3259).
--define(wxStyledTextCtrl_GetEdgeColour, 3260).
--define(wxStyledTextCtrl_SetEdgeColour, 3261).
--define(wxStyledTextCtrl_SearchAnchor, 3262).
--define(wxStyledTextCtrl_SearchNext, 3263).
--define(wxStyledTextCtrl_SearchPrev, 3264).
--define(wxStyledTextCtrl_LinesOnScreen, 3265).
--define(wxStyledTextCtrl_UsePopUp, 3266).
--define(wxStyledTextCtrl_SelectionIsRectangle, 3267).
--define(wxStyledTextCtrl_SetZoom, 3268).
--define(wxStyledTextCtrl_GetZoom, 3269).
--define(wxStyledTextCtrl_GetModEventMask, 3270).
--define(wxStyledTextCtrl_SetSTCFocus, 3271).
--define(wxStyledTextCtrl_GetSTCFocus, 3272).
--define(wxStyledTextCtrl_SetStatus, 3273).
--define(wxStyledTextCtrl_GetStatus, 3274).
--define(wxStyledTextCtrl_SetMouseDownCaptures, 3275).
--define(wxStyledTextCtrl_GetMouseDownCaptures, 3276).
--define(wxStyledTextCtrl_SetSTCCursor, 3277).
--define(wxStyledTextCtrl_GetSTCCursor, 3278).
--define(wxStyledTextCtrl_SetControlCharSymbol, 3279).
--define(wxStyledTextCtrl_GetControlCharSymbol, 3280).
--define(wxStyledTextCtrl_WordPartLeft, 3281).
--define(wxStyledTextCtrl_WordPartLeftExtend, 3282).
--define(wxStyledTextCtrl_WordPartRight, 3283).
--define(wxStyledTextCtrl_WordPartRightExtend, 3284).
--define(wxStyledTextCtrl_SetVisiblePolicy, 3285).
--define(wxStyledTextCtrl_DelLineLeft, 3286).
--define(wxStyledTextCtrl_DelLineRight, 3287).
--define(wxStyledTextCtrl_GetXOffset, 3288).
--define(wxStyledTextCtrl_ChooseCaretX, 3289).
--define(wxStyledTextCtrl_SetXCaretPolicy, 3290).
--define(wxStyledTextCtrl_SetYCaretPolicy, 3291).
--define(wxStyledTextCtrl_GetPrintWrapMode, 3292).
--define(wxStyledTextCtrl_SetHotspotActiveForeground, 3293).
--define(wxStyledTextCtrl_SetHotspotActiveBackground, 3294).
--define(wxStyledTextCtrl_SetHotspotActiveUnderline, 3295).
--define(wxStyledTextCtrl_SetHotspotSingleLine, 3296).
--define(wxStyledTextCtrl_ParaDownExtend, 3297).
--define(wxStyledTextCtrl_ParaUp, 3298).
--define(wxStyledTextCtrl_ParaUpExtend, 3299).
--define(wxStyledTextCtrl_PositionBefore, 3300).
--define(wxStyledTextCtrl_PositionAfter, 3301).
--define(wxStyledTextCtrl_CopyRange, 3302).
--define(wxStyledTextCtrl_CopyText, 3303).
--define(wxStyledTextCtrl_SetSelectionMode, 3304).
--define(wxStyledTextCtrl_GetSelectionMode, 3305).
--define(wxStyledTextCtrl_LineDownRectExtend, 3306).
--define(wxStyledTextCtrl_LineUpRectExtend, 3307).
--define(wxStyledTextCtrl_CharLeftRectExtend, 3308).
--define(wxStyledTextCtrl_CharRightRectExtend, 3309).
--define(wxStyledTextCtrl_HomeRectExtend, 3310).
--define(wxStyledTextCtrl_VCHomeRectExtend, 3311).
--define(wxStyledTextCtrl_LineEndRectExtend, 3312).
--define(wxStyledTextCtrl_PageUpRectExtend, 3313).
--define(wxStyledTextCtrl_PageDownRectExtend, 3314).
--define(wxStyledTextCtrl_StutteredPageUp, 3315).
--define(wxStyledTextCtrl_StutteredPageUpExtend, 3316).
--define(wxStyledTextCtrl_StutteredPageDown, 3317).
--define(wxStyledTextCtrl_StutteredPageDownExtend, 3318).
--define(wxStyledTextCtrl_WordLeftEnd, 3319).
--define(wxStyledTextCtrl_WordLeftEndExtend, 3320).
--define(wxStyledTextCtrl_WordRightEnd, 3321).
--define(wxStyledTextCtrl_WordRightEndExtend, 3322).
--define(wxStyledTextCtrl_SetWhitespaceChars, 3323).
--define(wxStyledTextCtrl_SetCharsDefault, 3324).
--define(wxStyledTextCtrl_AutoCompGetCurrent, 3325).
--define(wxStyledTextCtrl_Allocate, 3326).
--define(wxStyledTextCtrl_FindColumn, 3327).
--define(wxStyledTextCtrl_GetCaretSticky, 3328).
--define(wxStyledTextCtrl_SetCaretSticky, 3329).
--define(wxStyledTextCtrl_ToggleCaretSticky, 3330).
--define(wxStyledTextCtrl_SetPasteConvertEndings, 3331).
--define(wxStyledTextCtrl_GetPasteConvertEndings, 3332).
--define(wxStyledTextCtrl_SelectionDuplicate, 3333).
--define(wxStyledTextCtrl_SetCaretLineBackAlpha, 3334).
--define(wxStyledTextCtrl_GetCaretLineBackAlpha, 3335).
--define(wxStyledTextCtrl_StartRecord, 3336).
--define(wxStyledTextCtrl_StopRecord, 3337).
--define(wxStyledTextCtrl_SetLexer, 3338).
--define(wxStyledTextCtrl_GetLexer, 3339).
--define(wxStyledTextCtrl_Colourise, 3340).
--define(wxStyledTextCtrl_SetProperty, 3341).
--define(wxStyledTextCtrl_SetKeyWords, 3342).
--define(wxStyledTextCtrl_SetLexerLanguage, 3343).
--define(wxStyledTextCtrl_GetProperty, 3344).
--define(wxStyledTextCtrl_GetStyleBitsNeeded, 3345).
--define(wxStyledTextCtrl_GetCurrentLine, 3346).
--define(wxStyledTextCtrl_StyleSetSpec, 3347).
--define(wxStyledTextCtrl_StyleSetFont, 3348).
--define(wxStyledTextCtrl_StyleSetFontAttr, 3349).
--define(wxStyledTextCtrl_StyleSetCharacterSet, 3350).
--define(wxStyledTextCtrl_StyleSetFontEncoding, 3351).
--define(wxStyledTextCtrl_CmdKeyExecute, 3352).
--define(wxStyledTextCtrl_SetMargins, 3353).
--define(wxStyledTextCtrl_GetSelection, 3354).
--define(wxStyledTextCtrl_PointFromPosition, 3355).
--define(wxStyledTextCtrl_ScrollToLine, 3356).
--define(wxStyledTextCtrl_ScrollToColumn, 3357).
--define(wxStyledTextCtrl_SendMsg, 3358).
--define(wxStyledTextCtrl_SetVScrollBar, 3359).
--define(wxStyledTextCtrl_SetHScrollBar, 3360).
--define(wxStyledTextCtrl_GetLastKeydownProcessed, 3361).
--define(wxStyledTextCtrl_SetLastKeydownProcessed, 3362).
--define(wxStyledTextCtrl_SaveFile, 3363).
--define(wxStyledTextCtrl_LoadFile, 3364).
--define(wxStyledTextCtrl_DoDragOver, 3365).
--define(wxStyledTextCtrl_DoDropText, 3366).
--define(wxStyledTextCtrl_GetUseAntiAliasing, 3367).
--define(wxStyledTextCtrl_AddTextRaw, 3368).
--define(wxStyledTextCtrl_InsertTextRaw, 3369).
--define(wxStyledTextCtrl_GetCurLineRaw, 3370).
--define(wxStyledTextCtrl_GetLineRaw, 3371).
--define(wxStyledTextCtrl_GetSelectedTextRaw, 3372).
--define(wxStyledTextCtrl_GetTextRangeRaw, 3373).
--define(wxStyledTextCtrl_SetTextRaw, 3374).
--define(wxStyledTextCtrl_GetTextRaw, 3375).
--define(wxStyledTextCtrl_AppendTextRaw, 3376).
--define(wxArtProvider_GetBitmap, 3377).
--define(wxArtProvider_GetIcon, 3378).
--define(wxTreeEvent_GetKeyCode, 3379).
--define(wxTreeEvent_GetItem, 3380).
--define(wxTreeEvent_GetKeyEvent, 3381).
--define(wxTreeEvent_GetLabel, 3382).
--define(wxTreeEvent_GetOldItem, 3383).
--define(wxTreeEvent_GetPoint, 3384).
--define(wxTreeEvent_IsEditCancelled, 3385).
--define(wxTreeEvent_SetToolTip, 3386).
--define(wxNotebookEvent_GetOldSelection, 3387).
--define(wxNotebookEvent_GetSelection, 3388).
--define(wxNotebookEvent_SetOldSelection, 3389).
--define(wxNotebookEvent_SetSelection, 3390).
--define(wxFileDataObject_new, 3391).
--define(wxFileDataObject_AddFile, 3392).
--define(wxFileDataObject_GetFilenames, 3393).
--define(wxFileDataObject_destroy, 3394).
--define(wxTextDataObject_new, 3395).
--define(wxTextDataObject_GetTextLength, 3396).
--define(wxTextDataObject_GetText, 3397).
--define(wxTextDataObject_SetText, 3398).
--define(wxTextDataObject_destroy, 3399).
--define(wxBitmapDataObject_new_1_1, 3400).
--define(wxBitmapDataObject_new_1_0, 3401).
--define(wxBitmapDataObject_GetBitmap, 3402).
--define(wxBitmapDataObject_SetBitmap, 3403).
--define(wxBitmapDataObject_destroy, 3404).
--define(wxClipboard_new, 3406).
--define(wxClipboard_destruct, 3407).
--define(wxClipboard_AddData, 3408).
--define(wxClipboard_Clear, 3409).
--define(wxClipboard_Close, 3410).
--define(wxClipboard_Flush, 3411).
--define(wxClipboard_GetData, 3412).
--define(wxClipboard_IsOpened, 3413).
--define(wxClipboard_Open, 3414).
--define(wxClipboard_SetData, 3415).
--define(wxClipboard_UsePrimarySelection, 3417).
--define(wxClipboard_IsSupported, 3418).
--define(wxClipboard_Get, 3419).
--define(wxSpinEvent_GetPosition, 3420).
--define(wxSpinEvent_SetPosition, 3421).
--define(wxSplitterWindow_new_0, 3422).
--define(wxSplitterWindow_new_2, 3423).
--define(wxSplitterWindow_destruct, 3424).
--define(wxSplitterWindow_Create, 3425).
--define(wxSplitterWindow_GetMinimumPaneSize, 3426).
--define(wxSplitterWindow_GetSashGravity, 3427).
--define(wxSplitterWindow_GetSashPosition, 3428).
--define(wxSplitterWindow_GetSplitMode, 3429).
--define(wxSplitterWindow_GetWindow1, 3430).
--define(wxSplitterWindow_GetWindow2, 3431).
--define(wxSplitterWindow_Initialize, 3432).
--define(wxSplitterWindow_IsSplit, 3433).
--define(wxSplitterWindow_ReplaceWindow, 3434).
--define(wxSplitterWindow_SetSashGravity, 3435).
--define(wxSplitterWindow_SetSashPosition, 3436).
--define(wxSplitterWindow_SetSashSize, 3437).
--define(wxSplitterWindow_SetMinimumPaneSize, 3438).
--define(wxSplitterWindow_SetSplitMode, 3439).
--define(wxSplitterWindow_SplitHorizontally, 3440).
--define(wxSplitterWindow_SplitVertically, 3441).
--define(wxSplitterWindow_Unsplit, 3442).
--define(wxSplitterWindow_UpdateSize, 3443).
--define(wxSplitterEvent_GetSashPosition, 3444).
--define(wxSplitterEvent_GetX, 3445).
--define(wxSplitterEvent_GetY, 3446).
--define(wxSplitterEvent_GetWindowBeingRemoved, 3447).
--define(wxSplitterEvent_SetSashPosition, 3448).
--define(wxHtmlWindow_new_0, 3449).
--define(wxHtmlWindow_new_2, 3450).
--define(wxHtmlWindow_AppendToPage, 3451).
--define(wxHtmlWindow_GetOpenedAnchor, 3452).
--define(wxHtmlWindow_GetOpenedPage, 3453).
--define(wxHtmlWindow_GetOpenedPageTitle, 3454).
--define(wxHtmlWindow_GetRelatedFrame, 3455).
--define(wxHtmlWindow_HistoryBack, 3456).
--define(wxHtmlWindow_HistoryCanBack, 3457).
--define(wxHtmlWindow_HistoryCanForward, 3458).
--define(wxHtmlWindow_HistoryClear, 3459).
--define(wxHtmlWindow_HistoryForward, 3460).
--define(wxHtmlWindow_LoadFile, 3461).
--define(wxHtmlWindow_LoadPage, 3462).
--define(wxHtmlWindow_SelectAll, 3463).
--define(wxHtmlWindow_SelectionToText, 3464).
--define(wxHtmlWindow_SelectLine, 3465).
--define(wxHtmlWindow_SelectWord, 3466).
--define(wxHtmlWindow_SetBorders, 3467).
--define(wxHtmlWindow_SetFonts, 3468).
--define(wxHtmlWindow_SetPage, 3469).
--define(wxHtmlWindow_SetRelatedFrame, 3470).
--define(wxHtmlWindow_SetRelatedStatusBar, 3471).
--define(wxHtmlWindow_ToText, 3472).
--define(wxHtmlWindow_destroy, 3473).
--define(wxHtmlLinkEvent_GetLinkInfo, 3474).
--define(wxAuiNotebookEvent_SetSelection, 3475).
--define(wxAuiNotebookEvent_GetSelection, 3476).
--define(wxAuiNotebookEvent_SetOldSelection, 3477).
--define(wxAuiNotebookEvent_GetOldSelection, 3478).
--define(wxAuiNotebookEvent_SetDragSource, 3479).
--define(wxAuiNotebookEvent_GetDragSource, 3480).
--define(wxAuiManagerEvent_SetManager, 3481).
--define(wxAuiManagerEvent_GetManager, 3482).
--define(wxAuiManagerEvent_SetPane, 3483).
--define(wxAuiManagerEvent_GetPane, 3484).
--define(wxAuiManagerEvent_SetButton, 3485).
--define(wxAuiManagerEvent_GetButton, 3486).
--define(wxAuiManagerEvent_SetDC, 3487).
--define(wxAuiManagerEvent_GetDC, 3488).
--define(wxAuiManagerEvent_Veto, 3489).
--define(wxAuiManagerEvent_GetVeto, 3490).
--define(wxAuiManagerEvent_SetCanVeto, 3491).
--define(wxAuiManagerEvent_CanVeto, 3492).
--define(wxLogNull_new, 3493).
--define(wxLogNull_destroy, 3494).
+-define(wxTreeCtrl_EditLabel, 2010).
+-define(wxTreeCtrl_EnsureVisible, 2011).
+-define(wxTreeCtrl_Expand, 2012).
+-define(wxTreeCtrl_GetBoundingRect, 2013).
+-define(wxTreeCtrl_GetChildrenCount, 2015).
+-define(wxTreeCtrl_GetCount, 2016).
+-define(wxTreeCtrl_GetEditControl, 2017).
+-define(wxTreeCtrl_GetFirstChild, 2018).
+-define(wxTreeCtrl_GetNextChild, 2019).
+-define(wxTreeCtrl_GetFirstVisibleItem, 2020).
+-define(wxTreeCtrl_GetImageList, 2021).
+-define(wxTreeCtrl_GetIndent, 2022).
+-define(wxTreeCtrl_GetItemBackgroundColour, 2023).
+-define(wxTreeCtrl_GetItemData, 2024).
+-define(wxTreeCtrl_GetItemFont, 2025).
+-define(wxTreeCtrl_GetItemImage_1, 2026).
+-define(wxTreeCtrl_GetItemImage_2, 2027).
+-define(wxTreeCtrl_GetItemText, 2028).
+-define(wxTreeCtrl_GetItemTextColour, 2029).
+-define(wxTreeCtrl_GetLastChild, 2030).
+-define(wxTreeCtrl_GetNextSibling, 2031).
+-define(wxTreeCtrl_GetNextVisible, 2032).
+-define(wxTreeCtrl_GetItemParent, 2033).
+-define(wxTreeCtrl_GetPrevSibling, 2034).
+-define(wxTreeCtrl_GetPrevVisible, 2035).
+-define(wxTreeCtrl_GetRootItem, 2036).
+-define(wxTreeCtrl_GetSelection, 2037).
+-define(wxTreeCtrl_GetSelections, 2038).
+-define(wxTreeCtrl_GetStateImageList, 2039).
+-define(wxTreeCtrl_HitTest, 2040).
+-define(wxTreeCtrl_InsertItem, 2042).
+-define(wxTreeCtrl_IsBold, 2043).
+-define(wxTreeCtrl_IsExpanded, 2044).
+-define(wxTreeCtrl_IsSelected, 2045).
+-define(wxTreeCtrl_IsVisible, 2046).
+-define(wxTreeCtrl_ItemHasChildren, 2047).
+-define(wxTreeCtrl_PrependItem, 2048).
+-define(wxTreeCtrl_ScrollTo, 2049).
+-define(wxTreeCtrl_SelectItem_1, 2050).
+-define(wxTreeCtrl_SelectItem_2, 2051).
+-define(wxTreeCtrl_SetIndent, 2052).
+-define(wxTreeCtrl_SetImageList, 2053).
+-define(wxTreeCtrl_SetItemBackgroundColour, 2054).
+-define(wxTreeCtrl_SetItemBold, 2055).
+-define(wxTreeCtrl_SetItemData, 2056).
+-define(wxTreeCtrl_SetItemDropHighlight, 2057).
+-define(wxTreeCtrl_SetItemFont, 2058).
+-define(wxTreeCtrl_SetItemHasChildren, 2059).
+-define(wxTreeCtrl_SetItemImage_2, 2060).
+-define(wxTreeCtrl_SetItemImage_3, 2061).
+-define(wxTreeCtrl_SetItemText, 2062).
+-define(wxTreeCtrl_SetItemTextColour, 2063).
+-define(wxTreeCtrl_SetStateImageList, 2064).
+-define(wxTreeCtrl_SetWindowStyle, 2065).
+-define(wxTreeCtrl_SortChildren, 2066).
+-define(wxTreeCtrl_Toggle, 2067).
+-define(wxTreeCtrl_ToggleItemSelection, 2068).
+-define(wxTreeCtrl_Unselect, 2069).
+-define(wxTreeCtrl_UnselectAll, 2070).
+-define(wxTreeCtrl_UnselectItem, 2071).
+-define(wxScrollBar_new_0, 2072).
+-define(wxScrollBar_new_3, 2073).
+-define(wxScrollBar_destruct, 2074).
+-define(wxScrollBar_Create, 2075).
+-define(wxScrollBar_GetRange, 2076).
+-define(wxScrollBar_GetPageSize, 2077).
+-define(wxScrollBar_GetThumbPosition, 2078).
+-define(wxScrollBar_GetThumbSize, 2079).
+-define(wxScrollBar_SetThumbPosition, 2080).
+-define(wxScrollBar_SetScrollbar, 2081).
+-define(wxSpinButton_new_2, 2083).
+-define(wxSpinButton_new_0, 2084).
+-define(wxSpinButton_Create, 2085).
+-define(wxSpinButton_GetMax, 2086).
+-define(wxSpinButton_GetMin, 2087).
+-define(wxSpinButton_GetValue, 2088).
+-define(wxSpinButton_SetRange, 2089).
+-define(wxSpinButton_SetValue, 2090).
+-define(wxSpinButton_destroy, 2091).
+-define(wxSpinCtrl_new_0, 2092).
+-define(wxSpinCtrl_new_2, 2093).
+-define(wxSpinCtrl_Create, 2095).
+-define(wxSpinCtrl_SetValue_1_1, 2098).
+-define(wxSpinCtrl_SetValue_1_0, 2099).
+-define(wxSpinCtrl_GetValue, 2101).
+-define(wxSpinCtrl_SetRange, 2103).
+-define(wxSpinCtrl_SetSelection, 2104).
+-define(wxSpinCtrl_GetMin, 2106).
+-define(wxSpinCtrl_GetMax, 2108).
+-define(wxSpinCtrl_destroy, 2109).
+-define(wxStaticText_new_0, 2110).
+-define(wxStaticText_new_4, 2111).
+-define(wxStaticText_Create, 2112).
+-define(wxStaticText_GetLabel, 2113).
+-define(wxStaticText_SetLabel, 2114).
+-define(wxStaticText_Wrap, 2115).
+-define(wxStaticText_destroy, 2116).
+-define(wxStaticBitmap_new_0, 2117).
+-define(wxStaticBitmap_new_4, 2118).
+-define(wxStaticBitmap_Create, 2119).
+-define(wxStaticBitmap_GetBitmap, 2120).
+-define(wxStaticBitmap_SetBitmap, 2121).
+-define(wxStaticBitmap_destroy, 2122).
+-define(wxRadioBox_new, 2123).
+-define(wxRadioBox_destruct, 2125).
+-define(wxRadioBox_Create, 2126).
+-define(wxRadioBox_Enable_2, 2127).
+-define(wxRadioBox_Enable_1, 2128).
+-define(wxRadioBox_GetSelection, 2129).
+-define(wxRadioBox_GetString, 2130).
+-define(wxRadioBox_SetSelection, 2131).
+-define(wxRadioBox_Show_2, 2132).
+-define(wxRadioBox_Show_1, 2133).
+-define(wxRadioBox_GetColumnCount, 2134).
+-define(wxRadioBox_GetItemHelpText, 2135).
+-define(wxRadioBox_GetItemToolTip, 2136).
+-define(wxRadioBox_GetItemFromPoint, 2138).
+-define(wxRadioBox_GetRowCount, 2139).
+-define(wxRadioBox_IsItemEnabled, 2140).
+-define(wxRadioBox_IsItemShown, 2141).
+-define(wxRadioBox_SetItemHelpText, 2142).
+-define(wxRadioBox_SetItemToolTip, 2143).
+-define(wxRadioButton_new_0, 2144).
+-define(wxRadioButton_new_4, 2145).
+-define(wxRadioButton_Create, 2146).
+-define(wxRadioButton_GetValue, 2147).
+-define(wxRadioButton_SetValue, 2148).
+-define(wxRadioButton_destroy, 2149).
+-define(wxSlider_new_6, 2151).
+-define(wxSlider_new_0, 2152).
+-define(wxSlider_Create, 2153).
+-define(wxSlider_GetLineSize, 2154).
+-define(wxSlider_GetMax, 2155).
+-define(wxSlider_GetMin, 2156).
+-define(wxSlider_GetPageSize, 2157).
+-define(wxSlider_GetThumbLength, 2158).
+-define(wxSlider_GetValue, 2159).
+-define(wxSlider_SetLineSize, 2160).
+-define(wxSlider_SetPageSize, 2161).
+-define(wxSlider_SetRange, 2162).
+-define(wxSlider_SetThumbLength, 2163).
+-define(wxSlider_SetValue, 2164).
+-define(wxSlider_destroy, 2165).
+-define(wxDialog_new_4, 2167).
+-define(wxDialog_new_0, 2168).
+-define(wxDialog_destruct, 2170).
+-define(wxDialog_Create, 2171).
+-define(wxDialog_CreateButtonSizer, 2172).
+-define(wxDialog_CreateStdDialogButtonSizer, 2173).
+-define(wxDialog_EndModal, 2174).
+-define(wxDialog_GetAffirmativeId, 2175).
+-define(wxDialog_GetReturnCode, 2176).
+-define(wxDialog_IsModal, 2177).
+-define(wxDialog_SetAffirmativeId, 2178).
+-define(wxDialog_SetReturnCode, 2179).
+-define(wxDialog_Show, 2180).
+-define(wxDialog_ShowModal, 2181).
+-define(wxColourDialog_new_0, 2182).
+-define(wxColourDialog_new_2, 2183).
+-define(wxColourDialog_destruct, 2184).
+-define(wxColourDialog_Create, 2185).
+-define(wxColourDialog_GetColourData, 2186).
+-define(wxColourData_new_0, 2187).
+-define(wxColourData_new_1, 2188).
+-define(wxColourData_destruct, 2189).
+-define(wxColourData_GetChooseFull, 2190).
+-define(wxColourData_GetColour, 2191).
+-define(wxColourData_GetCustomColour, 2193).
+-define(wxColourData_SetChooseFull, 2194).
+-define(wxColourData_SetColour, 2195).
+-define(wxColourData_SetCustomColour, 2196).
+-define(wxPalette_new_0, 2197).
+-define(wxPalette_new_4, 2198).
+-define(wxPalette_destruct, 2200).
+-define(wxPalette_Create, 2201).
+-define(wxPalette_GetColoursCount, 2202).
+-define(wxPalette_GetPixel, 2203).
+-define(wxPalette_GetRGB, 2204).
+-define(wxPalette_IsOk, 2205).
+-define(wxDirDialog_new, 2209).
+-define(wxDirDialog_destruct, 2210).
+-define(wxDirDialog_GetPath, 2211).
+-define(wxDirDialog_GetMessage, 2212).
+-define(wxDirDialog_SetMessage, 2213).
+-define(wxDirDialog_SetPath, 2214).
+-define(wxFileDialog_new, 2218).
+-define(wxFileDialog_destruct, 2219).
+-define(wxFileDialog_GetDirectory, 2220).
+-define(wxFileDialog_GetFilename, 2221).
+-define(wxFileDialog_GetFilenames, 2222).
+-define(wxFileDialog_GetFilterIndex, 2223).
+-define(wxFileDialog_GetMessage, 2224).
+-define(wxFileDialog_GetPath, 2225).
+-define(wxFileDialog_GetPaths, 2226).
+-define(wxFileDialog_GetWildcard, 2227).
+-define(wxFileDialog_SetDirectory, 2228).
+-define(wxFileDialog_SetFilename, 2229).
+-define(wxFileDialog_SetFilterIndex, 2230).
+-define(wxFileDialog_SetMessage, 2231).
+-define(wxFileDialog_SetPath, 2232).
+-define(wxFileDialog_SetWildcard, 2233).
+-define(wxPickerBase_SetInternalMargin, 2234).
+-define(wxPickerBase_GetInternalMargin, 2235).
+-define(wxPickerBase_SetTextCtrlProportion, 2236).
+-define(wxPickerBase_SetPickerCtrlProportion, 2237).
+-define(wxPickerBase_GetTextCtrlProportion, 2238).
+-define(wxPickerBase_GetPickerCtrlProportion, 2239).
+-define(wxPickerBase_HasTextCtrl, 2240).
+-define(wxPickerBase_GetTextCtrl, 2241).
+-define(wxPickerBase_IsTextCtrlGrowable, 2242).
+-define(wxPickerBase_SetPickerCtrlGrowable, 2243).
+-define(wxPickerBase_SetTextCtrlGrowable, 2244).
+-define(wxPickerBase_IsPickerCtrlGrowable, 2245).
+-define(wxFilePickerCtrl_new_0, 2246).
+-define(wxFilePickerCtrl_new_3, 2247).
+-define(wxFilePickerCtrl_Create, 2248).
+-define(wxFilePickerCtrl_GetPath, 2249).
+-define(wxFilePickerCtrl_SetPath, 2250).
+-define(wxFilePickerCtrl_destroy, 2251).
+-define(wxDirPickerCtrl_new_0, 2252).
+-define(wxDirPickerCtrl_new_3, 2253).
+-define(wxDirPickerCtrl_Create, 2254).
+-define(wxDirPickerCtrl_GetPath, 2255).
+-define(wxDirPickerCtrl_SetPath, 2256).
+-define(wxDirPickerCtrl_destroy, 2257).
+-define(wxColourPickerCtrl_new_0, 2258).
+-define(wxColourPickerCtrl_new_3, 2259).
+-define(wxColourPickerCtrl_Create, 2260).
+-define(wxColourPickerCtrl_GetColour, 2261).
+-define(wxColourPickerCtrl_SetColour_1_1, 2262).
+-define(wxColourPickerCtrl_SetColour_1_0, 2263).
+-define(wxColourPickerCtrl_destroy, 2264).
+-define(wxDatePickerCtrl_new_0, 2265).
+-define(wxDatePickerCtrl_new_3, 2266).
+-define(wxDatePickerCtrl_GetRange, 2267).
+-define(wxDatePickerCtrl_GetValue, 2268).
+-define(wxDatePickerCtrl_SetRange, 2269).
+-define(wxDatePickerCtrl_SetValue, 2270).
+-define(wxDatePickerCtrl_destroy, 2271).
+-define(wxFontPickerCtrl_new_0, 2272).
+-define(wxFontPickerCtrl_new_3, 2273).
+-define(wxFontPickerCtrl_Create, 2274).
+-define(wxFontPickerCtrl_GetSelectedFont, 2275).
+-define(wxFontPickerCtrl_SetSelectedFont, 2276).
+-define(wxFontPickerCtrl_GetMaxPointSize, 2277).
+-define(wxFontPickerCtrl_SetMaxPointSize, 2278).
+-define(wxFontPickerCtrl_destroy, 2279).
+-define(wxFindReplaceDialog_new_0, 2282).
+-define(wxFindReplaceDialog_new_4, 2283).
+-define(wxFindReplaceDialog_destruct, 2284).
+-define(wxFindReplaceDialog_Create, 2285).
+-define(wxFindReplaceDialog_GetData, 2286).
+-define(wxFindReplaceData_new_0, 2287).
+-define(wxFindReplaceData_new_1, 2288).
+-define(wxFindReplaceData_GetFindString, 2289).
+-define(wxFindReplaceData_GetReplaceString, 2290).
+-define(wxFindReplaceData_GetFlags, 2291).
+-define(wxFindReplaceData_SetFlags, 2292).
+-define(wxFindReplaceData_SetFindString, 2293).
+-define(wxFindReplaceData_SetReplaceString, 2294).
+-define(wxFindReplaceData_destroy, 2295).
+-define(wxMultiChoiceDialog_new_0, 2296).
+-define(wxMultiChoiceDialog_new_5, 2298).
+-define(wxMultiChoiceDialog_GetSelections, 2299).
+-define(wxMultiChoiceDialog_SetSelections, 2300).
+-define(wxMultiChoiceDialog_destroy, 2301).
+-define(wxSingleChoiceDialog_new_0, 2302).
+-define(wxSingleChoiceDialog_new_5, 2304).
+-define(wxSingleChoiceDialog_GetSelection, 2305).
+-define(wxSingleChoiceDialog_GetStringSelection, 2306).
+-define(wxSingleChoiceDialog_SetSelection, 2307).
+-define(wxSingleChoiceDialog_destroy, 2308).
+-define(wxTextEntryDialog_new, 2309).
+-define(wxTextEntryDialog_GetValue, 2310).
+-define(wxTextEntryDialog_SetValue, 2311).
+-define(wxTextEntryDialog_destroy, 2312).
+-define(wxPasswordEntryDialog_new, 2313).
+-define(wxPasswordEntryDialog_destroy, 2314).
+-define(wxFontData_new_0, 2315).
+-define(wxFontData_new_1, 2316).
+-define(wxFontData_destruct, 2317).
+-define(wxFontData_EnableEffects, 2318).
+-define(wxFontData_GetAllowSymbols, 2319).
+-define(wxFontData_GetColour, 2320).
+-define(wxFontData_GetChosenFont, 2321).
+-define(wxFontData_GetEnableEffects, 2322).
+-define(wxFontData_GetInitialFont, 2323).
+-define(wxFontData_GetShowHelp, 2324).
+-define(wxFontData_SetAllowSymbols, 2325).
+-define(wxFontData_SetChosenFont, 2326).
+-define(wxFontData_SetColour, 2327).
+-define(wxFontData_SetInitialFont, 2328).
+-define(wxFontData_SetRange, 2329).
+-define(wxFontData_SetShowHelp, 2330).
+-define(wxFontDialog_new_0, 2334).
+-define(wxFontDialog_new_2, 2336).
+-define(wxFontDialog_Create, 2338).
+-define(wxFontDialog_GetFontData, 2339).
+-define(wxFontDialog_destroy, 2341).
+-define(wxProgressDialog_new, 2342).
+-define(wxProgressDialog_destruct, 2343).
+-define(wxProgressDialog_Resume, 2344).
+-define(wxProgressDialog_Update_2, 2345).
+-define(wxProgressDialog_Update_0, 2346).
+-define(wxMessageDialog_new, 2347).
+-define(wxMessageDialog_destruct, 2348).
+-define(wxPageSetupDialog_new, 2349).
+-define(wxPageSetupDialog_destruct, 2350).
+-define(wxPageSetupDialog_GetPageSetupData, 2351).
+-define(wxPageSetupDialog_ShowModal, 2352).
+-define(wxPageSetupDialogData_new_0, 2353).
+-define(wxPageSetupDialogData_new_1_0, 2354).
+-define(wxPageSetupDialogData_new_1_1, 2355).
+-define(wxPageSetupDialogData_destruct, 2356).
+-define(wxPageSetupDialogData_EnableHelp, 2357).
+-define(wxPageSetupDialogData_EnableMargins, 2358).
+-define(wxPageSetupDialogData_EnableOrientation, 2359).
+-define(wxPageSetupDialogData_EnablePaper, 2360).
+-define(wxPageSetupDialogData_EnablePrinter, 2361).
+-define(wxPageSetupDialogData_GetDefaultMinMargins, 2362).
+-define(wxPageSetupDialogData_GetEnableMargins, 2363).
+-define(wxPageSetupDialogData_GetEnableOrientation, 2364).
+-define(wxPageSetupDialogData_GetEnablePaper, 2365).
+-define(wxPageSetupDialogData_GetEnablePrinter, 2366).
+-define(wxPageSetupDialogData_GetEnableHelp, 2367).
+-define(wxPageSetupDialogData_GetDefaultInfo, 2368).
+-define(wxPageSetupDialogData_GetMarginTopLeft, 2369).
+-define(wxPageSetupDialogData_GetMarginBottomRight, 2370).
+-define(wxPageSetupDialogData_GetMinMarginTopLeft, 2371).
+-define(wxPageSetupDialogData_GetMinMarginBottomRight, 2372).
+-define(wxPageSetupDialogData_GetPaperId, 2373).
+-define(wxPageSetupDialogData_GetPaperSize, 2374).
+-define(wxPageSetupDialogData_GetPrintData, 2376).
+-define(wxPageSetupDialogData_IsOk, 2377).
+-define(wxPageSetupDialogData_SetDefaultInfo, 2378).
+-define(wxPageSetupDialogData_SetDefaultMinMargins, 2379).
+-define(wxPageSetupDialogData_SetMarginTopLeft, 2380).
+-define(wxPageSetupDialogData_SetMarginBottomRight, 2381).
+-define(wxPageSetupDialogData_SetMinMarginTopLeft, 2382).
+-define(wxPageSetupDialogData_SetMinMarginBottomRight, 2383).
+-define(wxPageSetupDialogData_SetPaperId, 2384).
+-define(wxPageSetupDialogData_SetPaperSize_1_1, 2385).
+-define(wxPageSetupDialogData_SetPaperSize_1_0, 2386).
+-define(wxPageSetupDialogData_SetPrintData, 2387).
+-define(wxPrintDialog_new_2_0, 2388).
+-define(wxPrintDialog_new_2_1, 2389).
+-define(wxPrintDialog_destruct, 2390).
+-define(wxPrintDialog_GetPrintDialogData, 2391).
+-define(wxPrintDialog_GetPrintDC, 2392).
+-define(wxPrintDialogData_new_0, 2393).
+-define(wxPrintDialogData_new_1_1, 2394).
+-define(wxPrintDialogData_new_1_0, 2395).
+-define(wxPrintDialogData_destruct, 2396).
+-define(wxPrintDialogData_EnableHelp, 2397).
+-define(wxPrintDialogData_EnablePageNumbers, 2398).
+-define(wxPrintDialogData_EnablePrintToFile, 2399).
+-define(wxPrintDialogData_EnableSelection, 2400).
+-define(wxPrintDialogData_GetAllPages, 2401).
+-define(wxPrintDialogData_GetCollate, 2402).
+-define(wxPrintDialogData_GetFromPage, 2403).
+-define(wxPrintDialogData_GetMaxPage, 2404).
+-define(wxPrintDialogData_GetMinPage, 2405).
+-define(wxPrintDialogData_GetNoCopies, 2406).
+-define(wxPrintDialogData_GetPrintData, 2407).
+-define(wxPrintDialogData_GetPrintToFile, 2408).
+-define(wxPrintDialogData_GetSelection, 2409).
+-define(wxPrintDialogData_GetToPage, 2410).
+-define(wxPrintDialogData_IsOk, 2411).
+-define(wxPrintDialogData_SetCollate, 2412).
+-define(wxPrintDialogData_SetFromPage, 2413).
+-define(wxPrintDialogData_SetMaxPage, 2414).
+-define(wxPrintDialogData_SetMinPage, 2415).
+-define(wxPrintDialogData_SetNoCopies, 2416).
+-define(wxPrintDialogData_SetPrintData, 2417).
+-define(wxPrintDialogData_SetPrintToFile, 2418).
+-define(wxPrintDialogData_SetSelection, 2419).
+-define(wxPrintDialogData_SetToPage, 2420).
+-define(wxPrintData_new_0, 2421).
+-define(wxPrintData_new_1, 2422).
+-define(wxPrintData_destruct, 2423).
+-define(wxPrintData_GetCollate, 2424).
+-define(wxPrintData_GetBin, 2425).
+-define(wxPrintData_GetColour, 2426).
+-define(wxPrintData_GetDuplex, 2427).
+-define(wxPrintData_GetNoCopies, 2428).
+-define(wxPrintData_GetOrientation, 2429).
+-define(wxPrintData_GetPaperId, 2430).
+-define(wxPrintData_GetPrinterName, 2431).
+-define(wxPrintData_GetQuality, 2432).
+-define(wxPrintData_IsOk, 2433).
+-define(wxPrintData_SetBin, 2434).
+-define(wxPrintData_SetCollate, 2435).
+-define(wxPrintData_SetColour, 2436).
+-define(wxPrintData_SetDuplex, 2437).
+-define(wxPrintData_SetNoCopies, 2438).
+-define(wxPrintData_SetOrientation, 2439).
+-define(wxPrintData_SetPaperId, 2440).
+-define(wxPrintData_SetPrinterName, 2441).
+-define(wxPrintData_SetQuality, 2442).
+-define(wxPrintPreview_new_2, 2445).
+-define(wxPrintPreview_new_3, 2446).
+-define(wxPrintPreview_destruct, 2448).
+-define(wxPrintPreview_GetCanvas, 2449).
+-define(wxPrintPreview_GetCurrentPage, 2450).
+-define(wxPrintPreview_GetFrame, 2451).
+-define(wxPrintPreview_GetMaxPage, 2452).
+-define(wxPrintPreview_GetMinPage, 2453).
+-define(wxPrintPreview_GetPrintout, 2454).
+-define(wxPrintPreview_GetPrintoutForPrinting, 2455).
+-define(wxPrintPreview_IsOk, 2456).
+-define(wxPrintPreview_PaintPage, 2457).
+-define(wxPrintPreview_Print, 2458).
+-define(wxPrintPreview_RenderPage, 2459).
+-define(wxPrintPreview_SetCanvas, 2460).
+-define(wxPrintPreview_SetCurrentPage, 2461).
+-define(wxPrintPreview_SetFrame, 2462).
+-define(wxPrintPreview_SetPrintout, 2463).
+-define(wxPrintPreview_SetZoom, 2464).
+-define(wxPreviewFrame_new, 2465).
+-define(wxPreviewFrame_destruct, 2466).
+-define(wxPreviewFrame_CreateControlBar, 2467).
+-define(wxPreviewFrame_CreateCanvas, 2468).
+-define(wxPreviewFrame_Initialize, 2469).
+-define(wxPreviewFrame_OnCloseWindow, 2470).
+-define(wxPreviewControlBar_new, 2471).
+-define(wxPreviewControlBar_destruct, 2472).
+-define(wxPreviewControlBar_CreateButtons, 2473).
+-define(wxPreviewControlBar_GetPrintPreview, 2474).
+-define(wxPreviewControlBar_GetZoomControl, 2475).
+-define(wxPreviewControlBar_SetZoomControl, 2476).
+-define(wxPrinter_new, 2478).
+-define(wxPrinter_CreateAbortWindow, 2479).
+-define(wxPrinter_GetAbort, 2480).
+-define(wxPrinter_GetLastError, 2481).
+-define(wxPrinter_GetPrintDialogData, 2482).
+-define(wxPrinter_Print, 2483).
+-define(wxPrinter_PrintDialog, 2484).
+-define(wxPrinter_ReportError, 2485).
+-define(wxPrinter_Setup, 2486).
+-define(wxPrinter_destroy, 2487).
+-define(wxXmlResource_new_1, 2488).
+-define(wxXmlResource_new_2, 2489).
+-define(wxXmlResource_destruct, 2490).
+-define(wxXmlResource_AttachUnknownControl, 2491).
+-define(wxXmlResource_ClearHandlers, 2492).
+-define(wxXmlResource_CompareVersion, 2493).
+-define(wxXmlResource_Get, 2494).
+-define(wxXmlResource_GetFlags, 2495).
+-define(wxXmlResource_GetVersion, 2496).
+-define(wxXmlResource_GetXRCID, 2497).
+-define(wxXmlResource_InitAllHandlers, 2498).
+-define(wxXmlResource_Load, 2499).
+-define(wxXmlResource_LoadBitmap, 2500).
+-define(wxXmlResource_LoadDialog_2, 2501).
+-define(wxXmlResource_LoadDialog_3, 2502).
+-define(wxXmlResource_LoadFrame_2, 2503).
+-define(wxXmlResource_LoadFrame_3, 2504).
+-define(wxXmlResource_LoadIcon, 2505).
+-define(wxXmlResource_LoadMenu, 2506).
+-define(wxXmlResource_LoadMenuBar_2, 2507).
+-define(wxXmlResource_LoadMenuBar_1, 2508).
+-define(wxXmlResource_LoadPanel_2, 2509).
+-define(wxXmlResource_LoadPanel_3, 2510).
+-define(wxXmlResource_LoadToolBar, 2511).
+-define(wxXmlResource_Set, 2512).
+-define(wxXmlResource_SetFlags, 2513).
+-define(wxXmlResource_Unload, 2514).
+-define(wxXmlResource_xrcctrl, 2515).
+-define(wxHtmlEasyPrinting_new, 2516).
+-define(wxHtmlEasyPrinting_destruct, 2517).
+-define(wxHtmlEasyPrinting_GetPrintData, 2518).
+-define(wxHtmlEasyPrinting_GetPageSetupData, 2519).
+-define(wxHtmlEasyPrinting_PreviewFile, 2520).
+-define(wxHtmlEasyPrinting_PreviewText, 2521).
+-define(wxHtmlEasyPrinting_PrintFile, 2522).
+-define(wxHtmlEasyPrinting_PrintText, 2523).
+-define(wxHtmlEasyPrinting_PageSetup, 2524).
+-define(wxHtmlEasyPrinting_SetFonts, 2525).
+-define(wxHtmlEasyPrinting_SetHeader, 2526).
+-define(wxHtmlEasyPrinting_SetFooter, 2527).
+-define(wxGLCanvas_new_2, 2529).
+-define(wxGLCanvas_new_3_1, 2530).
+-define(wxGLCanvas_new_3_0, 2531).
+-define(wxGLCanvas_GetContext, 2532).
+-define(wxGLCanvas_SetCurrent, 2534).
+-define(wxGLCanvas_SwapBuffers, 2535).
+-define(wxGLCanvas_destroy, 2536).
+-define(wxAuiManager_new, 2537).
+-define(wxAuiManager_destruct, 2538).
+-define(wxAuiManager_AddPane_2_1, 2539).
+-define(wxAuiManager_AddPane_3, 2540).
+-define(wxAuiManager_AddPane_2_0, 2541).
+-define(wxAuiManager_DetachPane, 2542).
+-define(wxAuiManager_GetAllPanes, 2543).
+-define(wxAuiManager_GetArtProvider, 2544).
+-define(wxAuiManager_GetDockSizeConstraint, 2545).
+-define(wxAuiManager_GetFlags, 2546).
+-define(wxAuiManager_GetManagedWindow, 2547).
+-define(wxAuiManager_GetManager, 2548).
+-define(wxAuiManager_GetPane_1_1, 2549).
+-define(wxAuiManager_GetPane_1_0, 2550).
+-define(wxAuiManager_HideHint, 2551).
+-define(wxAuiManager_InsertPane, 2552).
+-define(wxAuiManager_LoadPaneInfo, 2553).
+-define(wxAuiManager_LoadPerspective, 2554).
+-define(wxAuiManager_SavePaneInfo, 2555).
+-define(wxAuiManager_SavePerspective, 2556).
+-define(wxAuiManager_SetArtProvider, 2557).
+-define(wxAuiManager_SetDockSizeConstraint, 2558).
+-define(wxAuiManager_SetFlags, 2559).
+-define(wxAuiManager_SetManagedWindow, 2560).
+-define(wxAuiManager_ShowHint, 2561).
+-define(wxAuiManager_UnInit, 2562).
+-define(wxAuiManager_Update, 2563).
+-define(wxAuiPaneInfo_new_0, 2564).
+-define(wxAuiPaneInfo_new_1, 2565).
+-define(wxAuiPaneInfo_destruct, 2566).
+-define(wxAuiPaneInfo_BestSize_1, 2567).
+-define(wxAuiPaneInfo_BestSize_2, 2568).
+-define(wxAuiPaneInfo_Bottom, 2569).
+-define(wxAuiPaneInfo_BottomDockable, 2570).
+-define(wxAuiPaneInfo_Caption, 2571).
+-define(wxAuiPaneInfo_CaptionVisible, 2572).
+-define(wxAuiPaneInfo_Centre, 2573).
+-define(wxAuiPaneInfo_CentrePane, 2574).
+-define(wxAuiPaneInfo_CloseButton, 2575).
+-define(wxAuiPaneInfo_DefaultPane, 2576).
+-define(wxAuiPaneInfo_DestroyOnClose, 2577).
+-define(wxAuiPaneInfo_Direction, 2578).
+-define(wxAuiPaneInfo_Dock, 2579).
+-define(wxAuiPaneInfo_Dockable, 2580).
+-define(wxAuiPaneInfo_Fixed, 2581).
+-define(wxAuiPaneInfo_Float, 2582).
+-define(wxAuiPaneInfo_Floatable, 2583).
+-define(wxAuiPaneInfo_FloatingPosition_1, 2584).
+-define(wxAuiPaneInfo_FloatingPosition_2, 2585).
+-define(wxAuiPaneInfo_FloatingSize_1, 2586).
+-define(wxAuiPaneInfo_FloatingSize_2, 2587).
+-define(wxAuiPaneInfo_Gripper, 2588).
+-define(wxAuiPaneInfo_GripperTop, 2589).
+-define(wxAuiPaneInfo_HasBorder, 2590).
+-define(wxAuiPaneInfo_HasCaption, 2591).
+-define(wxAuiPaneInfo_HasCloseButton, 2592).
+-define(wxAuiPaneInfo_HasFlag, 2593).
+-define(wxAuiPaneInfo_HasGripper, 2594).
+-define(wxAuiPaneInfo_HasGripperTop, 2595).
+-define(wxAuiPaneInfo_HasMaximizeButton, 2596).
+-define(wxAuiPaneInfo_HasMinimizeButton, 2597).
+-define(wxAuiPaneInfo_HasPinButton, 2598).
+-define(wxAuiPaneInfo_Hide, 2599).
+-define(wxAuiPaneInfo_IsBottomDockable, 2600).
+-define(wxAuiPaneInfo_IsDocked, 2601).
+-define(wxAuiPaneInfo_IsFixed, 2602).
+-define(wxAuiPaneInfo_IsFloatable, 2603).
+-define(wxAuiPaneInfo_IsFloating, 2604).
+-define(wxAuiPaneInfo_IsLeftDockable, 2605).
+-define(wxAuiPaneInfo_IsMovable, 2606).
+-define(wxAuiPaneInfo_IsOk, 2607).
+-define(wxAuiPaneInfo_IsResizable, 2608).
+-define(wxAuiPaneInfo_IsRightDockable, 2609).
+-define(wxAuiPaneInfo_IsShown, 2610).
+-define(wxAuiPaneInfo_IsToolbar, 2611).
+-define(wxAuiPaneInfo_IsTopDockable, 2612).
+-define(wxAuiPaneInfo_Layer, 2613).
+-define(wxAuiPaneInfo_Left, 2614).
+-define(wxAuiPaneInfo_LeftDockable, 2615).
+-define(wxAuiPaneInfo_MaxSize_1, 2616).
+-define(wxAuiPaneInfo_MaxSize_2, 2617).
+-define(wxAuiPaneInfo_MaximizeButton, 2618).
+-define(wxAuiPaneInfo_MinSize_1, 2619).
+-define(wxAuiPaneInfo_MinSize_2, 2620).
+-define(wxAuiPaneInfo_MinimizeButton, 2621).
+-define(wxAuiPaneInfo_Movable, 2622).
+-define(wxAuiPaneInfo_Name, 2623).
+-define(wxAuiPaneInfo_PaneBorder, 2624).
+-define(wxAuiPaneInfo_PinButton, 2625).
+-define(wxAuiPaneInfo_Position, 2626).
+-define(wxAuiPaneInfo_Resizable, 2627).
+-define(wxAuiPaneInfo_Right, 2628).
+-define(wxAuiPaneInfo_RightDockable, 2629).
+-define(wxAuiPaneInfo_Row, 2630).
+-define(wxAuiPaneInfo_SafeSet, 2631).
+-define(wxAuiPaneInfo_SetFlag, 2632).
+-define(wxAuiPaneInfo_Show, 2633).
+-define(wxAuiPaneInfo_ToolbarPane, 2634).
+-define(wxAuiPaneInfo_Top, 2635).
+-define(wxAuiPaneInfo_TopDockable, 2636).
+-define(wxAuiPaneInfo_Window, 2637).
+-define(wxAuiNotebook_new_0, 2638).
+-define(wxAuiNotebook_new_2, 2639).
+-define(wxAuiNotebook_AddPage, 2640).
+-define(wxAuiNotebook_Create, 2641).
+-define(wxAuiNotebook_DeletePage, 2642).
+-define(wxAuiNotebook_GetArtProvider, 2643).
+-define(wxAuiNotebook_GetPage, 2644).
+-define(wxAuiNotebook_GetPageBitmap, 2645).
+-define(wxAuiNotebook_GetPageCount, 2646).
+-define(wxAuiNotebook_GetPageIndex, 2647).
+-define(wxAuiNotebook_GetPageText, 2648).
+-define(wxAuiNotebook_GetSelection, 2649).
+-define(wxAuiNotebook_InsertPage, 2650).
+-define(wxAuiNotebook_RemovePage, 2651).
+-define(wxAuiNotebook_SetArtProvider, 2652).
+-define(wxAuiNotebook_SetFont, 2653).
+-define(wxAuiNotebook_SetPageBitmap, 2654).
+-define(wxAuiNotebook_SetPageText, 2655).
+-define(wxAuiNotebook_SetSelection, 2656).
+-define(wxAuiNotebook_SetTabCtrlHeight, 2657).
+-define(wxAuiNotebook_SetUniformBitmapSize, 2658).
+-define(wxAuiNotebook_destroy, 2659).
+-define(wxMDIParentFrame_new_0, 2660).
+-define(wxMDIParentFrame_new_4, 2661).
+-define(wxMDIParentFrame_destruct, 2662).
+-define(wxMDIParentFrame_ActivateNext, 2663).
+-define(wxMDIParentFrame_ActivatePrevious, 2664).
+-define(wxMDIParentFrame_ArrangeIcons, 2665).
+-define(wxMDIParentFrame_Cascade, 2666).
+-define(wxMDIParentFrame_Create, 2667).
+-define(wxMDIParentFrame_GetActiveChild, 2668).
+-define(wxMDIParentFrame_GetClientWindow, 2669).
+-define(wxMDIParentFrame_Tile, 2670).
+-define(wxMDIChildFrame_new_0, 2671).
+-define(wxMDIChildFrame_new_4, 2672).
+-define(wxMDIChildFrame_destruct, 2673).
+-define(wxMDIChildFrame_Activate, 2674).
+-define(wxMDIChildFrame_Create, 2675).
+-define(wxMDIChildFrame_Maximize, 2676).
+-define(wxMDIChildFrame_Restore, 2677).
+-define(wxMDIClientWindow_new_0, 2678).
+-define(wxMDIClientWindow_new_2, 2679).
+-define(wxMDIClientWindow_destruct, 2680).
+-define(wxMDIClientWindow_CreateClient, 2681).
+-define(wxLayoutAlgorithm_new, 2682).
+-define(wxLayoutAlgorithm_LayoutFrame, 2683).
+-define(wxLayoutAlgorithm_LayoutMDIFrame, 2684).
+-define(wxLayoutAlgorithm_LayoutWindow, 2685).
+-define(wxLayoutAlgorithm_destroy, 2686).
+-define(wxEvent_GetId, 2687).
+-define(wxEvent_GetSkipped, 2688).
+-define(wxEvent_GetTimestamp, 2689).
+-define(wxEvent_IsCommandEvent, 2690).
+-define(wxEvent_ResumePropagation, 2691).
+-define(wxEvent_ShouldPropagate, 2692).
+-define(wxEvent_Skip, 2693).
+-define(wxEvent_StopPropagation, 2694).
+-define(wxCommandEvent_getClientData, 2695).
+-define(wxCommandEvent_GetExtraLong, 2696).
+-define(wxCommandEvent_GetInt, 2697).
+-define(wxCommandEvent_GetSelection, 2698).
+-define(wxCommandEvent_GetString, 2699).
+-define(wxCommandEvent_IsChecked, 2700).
+-define(wxCommandEvent_IsSelection, 2701).
+-define(wxCommandEvent_SetInt, 2702).
+-define(wxCommandEvent_SetString, 2703).
+-define(wxScrollEvent_GetOrientation, 2704).
+-define(wxScrollEvent_GetPosition, 2705).
+-define(wxScrollWinEvent_GetOrientation, 2706).
+-define(wxScrollWinEvent_GetPosition, 2707).
+-define(wxMouseEvent_AltDown, 2708).
+-define(wxMouseEvent_Button, 2709).
+-define(wxMouseEvent_ButtonDClick, 2710).
+-define(wxMouseEvent_ButtonDown, 2711).
+-define(wxMouseEvent_ButtonUp, 2712).
+-define(wxMouseEvent_CmdDown, 2713).
+-define(wxMouseEvent_ControlDown, 2714).
+-define(wxMouseEvent_Dragging, 2715).
+-define(wxMouseEvent_Entering, 2716).
+-define(wxMouseEvent_GetButton, 2717).
+-define(wxMouseEvent_GetPosition, 2720).
+-define(wxMouseEvent_GetLogicalPosition, 2721).
+-define(wxMouseEvent_GetLinesPerAction, 2722).
+-define(wxMouseEvent_GetWheelRotation, 2723).
+-define(wxMouseEvent_GetWheelDelta, 2724).
+-define(wxMouseEvent_GetX, 2725).
+-define(wxMouseEvent_GetY, 2726).
+-define(wxMouseEvent_IsButton, 2727).
+-define(wxMouseEvent_IsPageScroll, 2728).
+-define(wxMouseEvent_Leaving, 2729).
+-define(wxMouseEvent_LeftDClick, 2730).
+-define(wxMouseEvent_LeftDown, 2731).
+-define(wxMouseEvent_LeftIsDown, 2732).
+-define(wxMouseEvent_LeftUp, 2733).
+-define(wxMouseEvent_MetaDown, 2734).
+-define(wxMouseEvent_MiddleDClick, 2735).
+-define(wxMouseEvent_MiddleDown, 2736).
+-define(wxMouseEvent_MiddleIsDown, 2737).
+-define(wxMouseEvent_MiddleUp, 2738).
+-define(wxMouseEvent_Moving, 2739).
+-define(wxMouseEvent_RightDClick, 2740).
+-define(wxMouseEvent_RightDown, 2741).
+-define(wxMouseEvent_RightIsDown, 2742).
+-define(wxMouseEvent_RightUp, 2743).
+-define(wxMouseEvent_ShiftDown, 2744).
+-define(wxSetCursorEvent_GetCursor, 2745).
+-define(wxSetCursorEvent_GetX, 2746).
+-define(wxSetCursorEvent_GetY, 2747).
+-define(wxSetCursorEvent_HasCursor, 2748).
+-define(wxSetCursorEvent_SetCursor, 2749).
+-define(wxKeyEvent_AltDown, 2750).
+-define(wxKeyEvent_CmdDown, 2751).
+-define(wxKeyEvent_ControlDown, 2752).
+-define(wxKeyEvent_GetKeyCode, 2753).
+-define(wxKeyEvent_GetModifiers, 2754).
+-define(wxKeyEvent_GetPosition, 2757).
+-define(wxKeyEvent_GetRawKeyCode, 2758).
+-define(wxKeyEvent_GetRawKeyFlags, 2759).
+-define(wxKeyEvent_GetUnicodeKey, 2760).
+-define(wxKeyEvent_GetX, 2761).
+-define(wxKeyEvent_GetY, 2762).
+-define(wxKeyEvent_HasModifiers, 2763).
+-define(wxKeyEvent_MetaDown, 2764).
+-define(wxKeyEvent_ShiftDown, 2765).
+-define(wxSizeEvent_GetSize, 2766).
+-define(wxMoveEvent_GetPosition, 2767).
+-define(wxEraseEvent_GetDC, 2768).
+-define(wxFocusEvent_GetWindow, 2769).
+-define(wxChildFocusEvent_GetWindow, 2770).
+-define(wxMenuEvent_GetMenu, 2771).
+-define(wxMenuEvent_GetMenuId, 2772).
+-define(wxMenuEvent_IsPopup, 2773).
+-define(wxCloseEvent_CanVeto, 2774).
+-define(wxCloseEvent_GetLoggingOff, 2775).
+-define(wxCloseEvent_SetCanVeto, 2776).
+-define(wxCloseEvent_SetLoggingOff, 2777).
+-define(wxCloseEvent_Veto, 2778).
+-define(wxShowEvent_SetShow, 2779).
+-define(wxShowEvent_GetShow, 2780).
+-define(wxIconizeEvent_Iconized, 2781).
+-define(wxJoystickEvent_ButtonDown, 2782).
+-define(wxJoystickEvent_ButtonIsDown, 2783).
+-define(wxJoystickEvent_ButtonUp, 2784).
+-define(wxJoystickEvent_GetButtonChange, 2785).
+-define(wxJoystickEvent_GetButtonState, 2786).
+-define(wxJoystickEvent_GetJoystick, 2787).
+-define(wxJoystickEvent_GetPosition, 2788).
+-define(wxJoystickEvent_GetZPosition, 2789).
+-define(wxJoystickEvent_IsButton, 2790).
+-define(wxJoystickEvent_IsMove, 2791).
+-define(wxJoystickEvent_IsZMove, 2792).
+-define(wxUpdateUIEvent_CanUpdate, 2793).
+-define(wxUpdateUIEvent_Check, 2794).
+-define(wxUpdateUIEvent_Enable, 2795).
+-define(wxUpdateUIEvent_Show, 2796).
+-define(wxUpdateUIEvent_GetChecked, 2797).
+-define(wxUpdateUIEvent_GetEnabled, 2798).
+-define(wxUpdateUIEvent_GetShown, 2799).
+-define(wxUpdateUIEvent_GetSetChecked, 2800).
+-define(wxUpdateUIEvent_GetSetEnabled, 2801).
+-define(wxUpdateUIEvent_GetSetShown, 2802).
+-define(wxUpdateUIEvent_GetSetText, 2803).
+-define(wxUpdateUIEvent_GetText, 2804).
+-define(wxUpdateUIEvent_GetMode, 2805).
+-define(wxUpdateUIEvent_GetUpdateInterval, 2806).
+-define(wxUpdateUIEvent_ResetUpdateTime, 2807).
+-define(wxUpdateUIEvent_SetMode, 2808).
+-define(wxUpdateUIEvent_SetText, 2809).
+-define(wxUpdateUIEvent_SetUpdateInterval, 2810).
+-define(wxMouseCaptureChangedEvent_GetCapturedWindow, 2811).
+-define(wxPaletteChangedEvent_SetChangedWindow, 2812).
+-define(wxPaletteChangedEvent_GetChangedWindow, 2813).
+-define(wxQueryNewPaletteEvent_SetPaletteRealized, 2814).
+-define(wxQueryNewPaletteEvent_GetPaletteRealized, 2815).
+-define(wxNavigationKeyEvent_GetDirection, 2816).
+-define(wxNavigationKeyEvent_SetDirection, 2817).
+-define(wxNavigationKeyEvent_IsWindowChange, 2818).
+-define(wxNavigationKeyEvent_SetWindowChange, 2819).
+-define(wxNavigationKeyEvent_IsFromTab, 2820).
+-define(wxNavigationKeyEvent_SetFromTab, 2821).
+-define(wxNavigationKeyEvent_GetCurrentFocus, 2822).
+-define(wxNavigationKeyEvent_SetCurrentFocus, 2823).
+-define(wxHelpEvent_GetOrigin, 2824).
+-define(wxHelpEvent_GetPosition, 2825).
+-define(wxHelpEvent_SetOrigin, 2826).
+-define(wxHelpEvent_SetPosition, 2827).
+-define(wxContextMenuEvent_GetPosition, 2828).
+-define(wxContextMenuEvent_SetPosition, 2829).
+-define(wxIdleEvent_CanSend, 2830).
+-define(wxIdleEvent_GetMode, 2831).
+-define(wxIdleEvent_RequestMore, 2832).
+-define(wxIdleEvent_MoreRequested, 2833).
+-define(wxIdleEvent_SetMode, 2834).
+-define(wxGridEvent_AltDown, 2835).
+-define(wxGridEvent_ControlDown, 2836).
+-define(wxGridEvent_GetCol, 2837).
+-define(wxGridEvent_GetPosition, 2838).
+-define(wxGridEvent_GetRow, 2839).
+-define(wxGridEvent_MetaDown, 2840).
+-define(wxGridEvent_Selecting, 2841).
+-define(wxGridEvent_ShiftDown, 2842).
+-define(wxNotifyEvent_Allow, 2843).
+-define(wxNotifyEvent_IsAllowed, 2844).
+-define(wxNotifyEvent_Veto, 2845).
+-define(wxSashEvent_GetEdge, 2846).
+-define(wxSashEvent_GetDragRect, 2847).
+-define(wxSashEvent_GetDragStatus, 2848).
+-define(wxListEvent_GetCacheFrom, 2849).
+-define(wxListEvent_GetCacheTo, 2850).
+-define(wxListEvent_GetKeyCode, 2851).
+-define(wxListEvent_GetIndex, 2852).
+-define(wxListEvent_GetColumn, 2853).
+-define(wxListEvent_GetPoint, 2854).
+-define(wxListEvent_GetLabel, 2855).
+-define(wxListEvent_GetText, 2856).
+-define(wxListEvent_GetImage, 2857).
+-define(wxListEvent_GetData, 2858).
+-define(wxListEvent_GetMask, 2859).
+-define(wxListEvent_GetItem, 2860).
+-define(wxListEvent_IsEditCancelled, 2861).
+-define(wxDateEvent_GetDate, 2862).
+-define(wxCalendarEvent_GetWeekDay, 2863).
+-define(wxFileDirPickerEvent_GetPath, 2864).
+-define(wxColourPickerEvent_GetColour, 2865).
+-define(wxFontPickerEvent_GetFont, 2866).
+-define(wxStyledTextEvent_GetPosition, 2867).
+-define(wxStyledTextEvent_GetKey, 2868).
+-define(wxStyledTextEvent_GetModifiers, 2869).
+-define(wxStyledTextEvent_GetModificationType, 2870).
+-define(wxStyledTextEvent_GetText, 2871).
+-define(wxStyledTextEvent_GetLength, 2872).
+-define(wxStyledTextEvent_GetLinesAdded, 2873).
+-define(wxStyledTextEvent_GetLine, 2874).
+-define(wxStyledTextEvent_GetFoldLevelNow, 2875).
+-define(wxStyledTextEvent_GetFoldLevelPrev, 2876).
+-define(wxStyledTextEvent_GetMargin, 2877).
+-define(wxStyledTextEvent_GetMessage, 2878).
+-define(wxStyledTextEvent_GetWParam, 2879).
+-define(wxStyledTextEvent_GetLParam, 2880).
+-define(wxStyledTextEvent_GetListType, 2881).
+-define(wxStyledTextEvent_GetX, 2882).
+-define(wxStyledTextEvent_GetY, 2883).
+-define(wxStyledTextEvent_GetDragText, 2884).
+-define(wxStyledTextEvent_GetDragAllowMove, 2885).
+-define(wxStyledTextEvent_GetDragResult, 2886).
+-define(wxStyledTextEvent_GetShift, 2887).
+-define(wxStyledTextEvent_GetControl, 2888).
+-define(wxStyledTextEvent_GetAlt, 2889).
+-define(utils_wxGetKeyState, 2890).
+-define(utils_wxGetMousePosition, 2891).
+-define(utils_wxGetMouseState, 2892).
+-define(utils_wxSetDetectableAutoRepeat, 2893).
+-define(utils_wxBell, 2894).
+-define(utils_wxFindMenuItemId, 2895).
+-define(utils_wxGenericFindWindowAtPoint, 2896).
+-define(utils_wxFindWindowAtPoint, 2897).
+-define(utils_wxBeginBusyCursor, 2898).
+-define(utils_wxEndBusyCursor, 2899).
+-define(utils_wxIsBusy, 2900).
+-define(utils_wxShutdown, 2901).
+-define(utils_wxShell, 2902).
+-define(utils_wxLaunchDefaultBrowser, 2903).
+-define(utils_wxGetEmailAddress, 2904).
+-define(utils_wxGetUserId, 2905).
+-define(utils_wxGetHomeDir, 2906).
+-define(utils_wxNewId, 2907).
+-define(utils_wxRegisterId, 2908).
+-define(utils_wxGetCurrentId, 2909).
+-define(utils_wxGetOsDescription, 2910).
+-define(utils_wxIsPlatformLittleEndian, 2911).
+-define(utils_wxIsPlatform64Bit, 2912).
+-define(wxPrintout_new, 2913).
+-define(wxPrintout_destruct, 2914).
+-define(wxPrintout_GetDC, 2915).
+-define(wxPrintout_GetPageSizeMM, 2916).
+-define(wxPrintout_GetPageSizePixels, 2917).
+-define(wxPrintout_GetPaperRectPixels, 2918).
+-define(wxPrintout_GetPPIPrinter, 2919).
+-define(wxPrintout_GetPPIScreen, 2920).
+-define(wxPrintout_GetTitle, 2921).
+-define(wxPrintout_IsPreview, 2922).
+-define(wxPrintout_FitThisSizeToPaper, 2923).
+-define(wxPrintout_FitThisSizeToPage, 2924).
+-define(wxPrintout_FitThisSizeToPageMargins, 2925).
+-define(wxPrintout_MapScreenSizeToPaper, 2926).
+-define(wxPrintout_MapScreenSizeToPage, 2927).
+-define(wxPrintout_MapScreenSizeToPageMargins, 2928).
+-define(wxPrintout_MapScreenSizeToDevice, 2929).
+-define(wxPrintout_GetLogicalPaperRect, 2930).
+-define(wxPrintout_GetLogicalPageRect, 2931).
+-define(wxPrintout_GetLogicalPageMarginsRect, 2932).
+-define(wxPrintout_SetLogicalOrigin, 2933).
+-define(wxPrintout_OffsetLogicalOrigin, 2934).
+-define(wxStyledTextCtrl_new_2, 2935).
+-define(wxStyledTextCtrl_new_0, 2936).
+-define(wxStyledTextCtrl_destruct, 2937).
+-define(wxStyledTextCtrl_Create, 2938).
+-define(wxStyledTextCtrl_AddText, 2939).
+-define(wxStyledTextCtrl_AddStyledText, 2940).
+-define(wxStyledTextCtrl_InsertText, 2941).
+-define(wxStyledTextCtrl_ClearAll, 2942).
+-define(wxStyledTextCtrl_ClearDocumentStyle, 2943).
+-define(wxStyledTextCtrl_GetLength, 2944).
+-define(wxStyledTextCtrl_GetCharAt, 2945).
+-define(wxStyledTextCtrl_GetCurrentPos, 2946).
+-define(wxStyledTextCtrl_GetAnchor, 2947).
+-define(wxStyledTextCtrl_GetStyleAt, 2948).
+-define(wxStyledTextCtrl_Redo, 2949).
+-define(wxStyledTextCtrl_SetUndoCollection, 2950).
+-define(wxStyledTextCtrl_SelectAll, 2951).
+-define(wxStyledTextCtrl_SetSavePoint, 2952).
+-define(wxStyledTextCtrl_GetStyledText, 2953).
+-define(wxStyledTextCtrl_CanRedo, 2954).
+-define(wxStyledTextCtrl_MarkerLineFromHandle, 2955).
+-define(wxStyledTextCtrl_MarkerDeleteHandle, 2956).
+-define(wxStyledTextCtrl_GetUndoCollection, 2957).
+-define(wxStyledTextCtrl_GetViewWhiteSpace, 2958).
+-define(wxStyledTextCtrl_SetViewWhiteSpace, 2959).
+-define(wxStyledTextCtrl_PositionFromPoint, 2960).
+-define(wxStyledTextCtrl_PositionFromPointClose, 2961).
+-define(wxStyledTextCtrl_GotoLine, 2962).
+-define(wxStyledTextCtrl_GotoPos, 2963).
+-define(wxStyledTextCtrl_SetAnchor, 2964).
+-define(wxStyledTextCtrl_GetCurLine, 2965).
+-define(wxStyledTextCtrl_GetEndStyled, 2966).
+-define(wxStyledTextCtrl_ConvertEOLs, 2967).
+-define(wxStyledTextCtrl_GetEOLMode, 2968).
+-define(wxStyledTextCtrl_SetEOLMode, 2969).
+-define(wxStyledTextCtrl_StartStyling, 2970).
+-define(wxStyledTextCtrl_SetStyling, 2971).
+-define(wxStyledTextCtrl_GetBufferedDraw, 2972).
+-define(wxStyledTextCtrl_SetBufferedDraw, 2973).
+-define(wxStyledTextCtrl_SetTabWidth, 2974).
+-define(wxStyledTextCtrl_GetTabWidth, 2975).
+-define(wxStyledTextCtrl_SetCodePage, 2976).
+-define(wxStyledTextCtrl_MarkerDefine, 2977).
+-define(wxStyledTextCtrl_MarkerSetForeground, 2978).
+-define(wxStyledTextCtrl_MarkerSetBackground, 2979).
+-define(wxStyledTextCtrl_MarkerAdd, 2980).
+-define(wxStyledTextCtrl_MarkerDelete, 2981).
+-define(wxStyledTextCtrl_MarkerDeleteAll, 2982).
+-define(wxStyledTextCtrl_MarkerGet, 2983).
+-define(wxStyledTextCtrl_MarkerNext, 2984).
+-define(wxStyledTextCtrl_MarkerPrevious, 2985).
+-define(wxStyledTextCtrl_MarkerDefineBitmap, 2986).
+-define(wxStyledTextCtrl_MarkerAddSet, 2987).
+-define(wxStyledTextCtrl_MarkerSetAlpha, 2988).
+-define(wxStyledTextCtrl_SetMarginType, 2989).
+-define(wxStyledTextCtrl_GetMarginType, 2990).
+-define(wxStyledTextCtrl_SetMarginWidth, 2991).
+-define(wxStyledTextCtrl_GetMarginWidth, 2992).
+-define(wxStyledTextCtrl_SetMarginMask, 2993).
+-define(wxStyledTextCtrl_GetMarginMask, 2994).
+-define(wxStyledTextCtrl_SetMarginSensitive, 2995).
+-define(wxStyledTextCtrl_GetMarginSensitive, 2996).
+-define(wxStyledTextCtrl_StyleClearAll, 2997).
+-define(wxStyledTextCtrl_StyleSetForeground, 2998).
+-define(wxStyledTextCtrl_StyleSetBackground, 2999).
+-define(wxStyledTextCtrl_StyleSetBold, 3000).
+-define(wxStyledTextCtrl_StyleSetItalic, 3001).
+-define(wxStyledTextCtrl_StyleSetSize, 3002).
+-define(wxStyledTextCtrl_StyleSetFaceName, 3003).
+-define(wxStyledTextCtrl_StyleSetEOLFilled, 3004).
+-define(wxStyledTextCtrl_StyleResetDefault, 3005).
+-define(wxStyledTextCtrl_StyleSetUnderline, 3006).
+-define(wxStyledTextCtrl_StyleSetCase, 3007).
+-define(wxStyledTextCtrl_StyleSetHotSpot, 3008).
+-define(wxStyledTextCtrl_SetSelForeground, 3009).
+-define(wxStyledTextCtrl_SetSelBackground, 3010).
+-define(wxStyledTextCtrl_GetSelAlpha, 3011).
+-define(wxStyledTextCtrl_SetSelAlpha, 3012).
+-define(wxStyledTextCtrl_SetCaretForeground, 3013).
+-define(wxStyledTextCtrl_CmdKeyAssign, 3014).
+-define(wxStyledTextCtrl_CmdKeyClear, 3015).
+-define(wxStyledTextCtrl_CmdKeyClearAll, 3016).
+-define(wxStyledTextCtrl_SetStyleBytes, 3017).
+-define(wxStyledTextCtrl_StyleSetVisible, 3018).
+-define(wxStyledTextCtrl_GetCaretPeriod, 3019).
+-define(wxStyledTextCtrl_SetCaretPeriod, 3020).
+-define(wxStyledTextCtrl_SetWordChars, 3021).
+-define(wxStyledTextCtrl_BeginUndoAction, 3022).
+-define(wxStyledTextCtrl_EndUndoAction, 3023).
+-define(wxStyledTextCtrl_IndicatorSetStyle, 3024).
+-define(wxStyledTextCtrl_IndicatorGetStyle, 3025).
+-define(wxStyledTextCtrl_IndicatorSetForeground, 3026).
+-define(wxStyledTextCtrl_IndicatorGetForeground, 3027).
+-define(wxStyledTextCtrl_SetWhitespaceForeground, 3028).
+-define(wxStyledTextCtrl_SetWhitespaceBackground, 3029).
+-define(wxStyledTextCtrl_GetStyleBits, 3030).
+-define(wxStyledTextCtrl_SetLineState, 3031).
+-define(wxStyledTextCtrl_GetLineState, 3032).
+-define(wxStyledTextCtrl_GetMaxLineState, 3033).
+-define(wxStyledTextCtrl_GetCaretLineVisible, 3034).
+-define(wxStyledTextCtrl_SetCaretLineVisible, 3035).
+-define(wxStyledTextCtrl_GetCaretLineBackground, 3036).
+-define(wxStyledTextCtrl_SetCaretLineBackground, 3037).
+-define(wxStyledTextCtrl_AutoCompShow, 3038).
+-define(wxStyledTextCtrl_AutoCompCancel, 3039).
+-define(wxStyledTextCtrl_AutoCompActive, 3040).
+-define(wxStyledTextCtrl_AutoCompPosStart, 3041).
+-define(wxStyledTextCtrl_AutoCompComplete, 3042).
+-define(wxStyledTextCtrl_AutoCompStops, 3043).
+-define(wxStyledTextCtrl_AutoCompSetSeparator, 3044).
+-define(wxStyledTextCtrl_AutoCompGetSeparator, 3045).
+-define(wxStyledTextCtrl_AutoCompSelect, 3046).
+-define(wxStyledTextCtrl_AutoCompSetCancelAtStart, 3047).
+-define(wxStyledTextCtrl_AutoCompGetCancelAtStart, 3048).
+-define(wxStyledTextCtrl_AutoCompSetFillUps, 3049).
+-define(wxStyledTextCtrl_AutoCompSetChooseSingle, 3050).
+-define(wxStyledTextCtrl_AutoCompGetChooseSingle, 3051).
+-define(wxStyledTextCtrl_AutoCompSetIgnoreCase, 3052).
+-define(wxStyledTextCtrl_AutoCompGetIgnoreCase, 3053).
+-define(wxStyledTextCtrl_UserListShow, 3054).
+-define(wxStyledTextCtrl_AutoCompSetAutoHide, 3055).
+-define(wxStyledTextCtrl_AutoCompGetAutoHide, 3056).
+-define(wxStyledTextCtrl_AutoCompSetDropRestOfWord, 3057).
+-define(wxStyledTextCtrl_AutoCompGetDropRestOfWord, 3058).
+-define(wxStyledTextCtrl_RegisterImage, 3059).
+-define(wxStyledTextCtrl_ClearRegisteredImages, 3060).
+-define(wxStyledTextCtrl_AutoCompGetTypeSeparator, 3061).
+-define(wxStyledTextCtrl_AutoCompSetTypeSeparator, 3062).
+-define(wxStyledTextCtrl_AutoCompSetMaxWidth, 3063).
+-define(wxStyledTextCtrl_AutoCompGetMaxWidth, 3064).
+-define(wxStyledTextCtrl_AutoCompSetMaxHeight, 3065).
+-define(wxStyledTextCtrl_AutoCompGetMaxHeight, 3066).
+-define(wxStyledTextCtrl_SetIndent, 3067).
+-define(wxStyledTextCtrl_GetIndent, 3068).
+-define(wxStyledTextCtrl_SetUseTabs, 3069).
+-define(wxStyledTextCtrl_GetUseTabs, 3070).
+-define(wxStyledTextCtrl_SetLineIndentation, 3071).
+-define(wxStyledTextCtrl_GetLineIndentation, 3072).
+-define(wxStyledTextCtrl_GetLineIndentPosition, 3073).
+-define(wxStyledTextCtrl_GetColumn, 3074).
+-define(wxStyledTextCtrl_SetUseHorizontalScrollBar, 3075).
+-define(wxStyledTextCtrl_GetUseHorizontalScrollBar, 3076).
+-define(wxStyledTextCtrl_SetIndentationGuides, 3077).
+-define(wxStyledTextCtrl_GetIndentationGuides, 3078).
+-define(wxStyledTextCtrl_SetHighlightGuide, 3079).
+-define(wxStyledTextCtrl_GetHighlightGuide, 3080).
+-define(wxStyledTextCtrl_GetLineEndPosition, 3081).
+-define(wxStyledTextCtrl_GetCodePage, 3082).
+-define(wxStyledTextCtrl_GetCaretForeground, 3083).
+-define(wxStyledTextCtrl_GetReadOnly, 3084).
+-define(wxStyledTextCtrl_SetCurrentPos, 3085).
+-define(wxStyledTextCtrl_SetSelectionStart, 3086).
+-define(wxStyledTextCtrl_GetSelectionStart, 3087).
+-define(wxStyledTextCtrl_SetSelectionEnd, 3088).
+-define(wxStyledTextCtrl_GetSelectionEnd, 3089).
+-define(wxStyledTextCtrl_SetPrintMagnification, 3090).
+-define(wxStyledTextCtrl_GetPrintMagnification, 3091).
+-define(wxStyledTextCtrl_SetPrintColourMode, 3092).
+-define(wxStyledTextCtrl_GetPrintColourMode, 3093).
+-define(wxStyledTextCtrl_FindText, 3094).
+-define(wxStyledTextCtrl_FormatRange, 3095).
+-define(wxStyledTextCtrl_GetFirstVisibleLine, 3096).
+-define(wxStyledTextCtrl_GetLine, 3097).
+-define(wxStyledTextCtrl_GetLineCount, 3098).
+-define(wxStyledTextCtrl_SetMarginLeft, 3099).
+-define(wxStyledTextCtrl_GetMarginLeft, 3100).
+-define(wxStyledTextCtrl_SetMarginRight, 3101).
+-define(wxStyledTextCtrl_GetMarginRight, 3102).
+-define(wxStyledTextCtrl_GetModify, 3103).
+-define(wxStyledTextCtrl_SetSelection, 3104).
+-define(wxStyledTextCtrl_GetSelectedText, 3105).
+-define(wxStyledTextCtrl_GetTextRange, 3106).
+-define(wxStyledTextCtrl_HideSelection, 3107).
+-define(wxStyledTextCtrl_LineFromPosition, 3108).
+-define(wxStyledTextCtrl_PositionFromLine, 3109).
+-define(wxStyledTextCtrl_LineScroll, 3110).
+-define(wxStyledTextCtrl_EnsureCaretVisible, 3111).
+-define(wxStyledTextCtrl_ReplaceSelection, 3112).
+-define(wxStyledTextCtrl_SetReadOnly, 3113).
+-define(wxStyledTextCtrl_CanPaste, 3114).
+-define(wxStyledTextCtrl_CanUndo, 3115).
+-define(wxStyledTextCtrl_EmptyUndoBuffer, 3116).
+-define(wxStyledTextCtrl_Undo, 3117).
+-define(wxStyledTextCtrl_Cut, 3118).
+-define(wxStyledTextCtrl_Copy, 3119).
+-define(wxStyledTextCtrl_Paste, 3120).
+-define(wxStyledTextCtrl_Clear, 3121).
+-define(wxStyledTextCtrl_SetText, 3122).
+-define(wxStyledTextCtrl_GetText, 3123).
+-define(wxStyledTextCtrl_GetTextLength, 3124).
+-define(wxStyledTextCtrl_GetOvertype, 3125).
+-define(wxStyledTextCtrl_SetCaretWidth, 3126).
+-define(wxStyledTextCtrl_GetCaretWidth, 3127).
+-define(wxStyledTextCtrl_SetTargetStart, 3128).
+-define(wxStyledTextCtrl_GetTargetStart, 3129).
+-define(wxStyledTextCtrl_SetTargetEnd, 3130).
+-define(wxStyledTextCtrl_GetTargetEnd, 3131).
+-define(wxStyledTextCtrl_ReplaceTarget, 3132).
+-define(wxStyledTextCtrl_SearchInTarget, 3133).
+-define(wxStyledTextCtrl_SetSearchFlags, 3134).
+-define(wxStyledTextCtrl_GetSearchFlags, 3135).
+-define(wxStyledTextCtrl_CallTipShow, 3136).
+-define(wxStyledTextCtrl_CallTipCancel, 3137).
+-define(wxStyledTextCtrl_CallTipActive, 3138).
+-define(wxStyledTextCtrl_CallTipPosAtStart, 3139).
+-define(wxStyledTextCtrl_CallTipSetHighlight, 3140).
+-define(wxStyledTextCtrl_CallTipSetBackground, 3141).
+-define(wxStyledTextCtrl_CallTipSetForeground, 3142).
+-define(wxStyledTextCtrl_CallTipSetForegroundHighlight, 3143).
+-define(wxStyledTextCtrl_CallTipUseStyle, 3144).
+-define(wxStyledTextCtrl_VisibleFromDocLine, 3145).
+-define(wxStyledTextCtrl_DocLineFromVisible, 3146).
+-define(wxStyledTextCtrl_WrapCount, 3147).
+-define(wxStyledTextCtrl_SetFoldLevel, 3148).
+-define(wxStyledTextCtrl_GetFoldLevel, 3149).
+-define(wxStyledTextCtrl_GetLastChild, 3150).
+-define(wxStyledTextCtrl_GetFoldParent, 3151).
+-define(wxStyledTextCtrl_ShowLines, 3152).
+-define(wxStyledTextCtrl_HideLines, 3153).
+-define(wxStyledTextCtrl_GetLineVisible, 3154).
+-define(wxStyledTextCtrl_SetFoldExpanded, 3155).
+-define(wxStyledTextCtrl_GetFoldExpanded, 3156).
+-define(wxStyledTextCtrl_ToggleFold, 3157).
+-define(wxStyledTextCtrl_EnsureVisible, 3158).
+-define(wxStyledTextCtrl_SetFoldFlags, 3159).
+-define(wxStyledTextCtrl_EnsureVisibleEnforcePolicy, 3160).
+-define(wxStyledTextCtrl_SetTabIndents, 3161).
+-define(wxStyledTextCtrl_GetTabIndents, 3162).
+-define(wxStyledTextCtrl_SetBackSpaceUnIndents, 3163).
+-define(wxStyledTextCtrl_GetBackSpaceUnIndents, 3164).
+-define(wxStyledTextCtrl_SetMouseDwellTime, 3165).
+-define(wxStyledTextCtrl_GetMouseDwellTime, 3166).
+-define(wxStyledTextCtrl_WordStartPosition, 3167).
+-define(wxStyledTextCtrl_WordEndPosition, 3168).
+-define(wxStyledTextCtrl_SetWrapMode, 3169).
+-define(wxStyledTextCtrl_GetWrapMode, 3170).
+-define(wxStyledTextCtrl_SetWrapVisualFlags, 3171).
+-define(wxStyledTextCtrl_GetWrapVisualFlags, 3172).
+-define(wxStyledTextCtrl_SetWrapVisualFlagsLocation, 3173).
+-define(wxStyledTextCtrl_GetWrapVisualFlagsLocation, 3174).
+-define(wxStyledTextCtrl_SetWrapStartIndent, 3175).
+-define(wxStyledTextCtrl_GetWrapStartIndent, 3176).
+-define(wxStyledTextCtrl_SetLayoutCache, 3177).
+-define(wxStyledTextCtrl_GetLayoutCache, 3178).
+-define(wxStyledTextCtrl_SetScrollWidth, 3179).
+-define(wxStyledTextCtrl_GetScrollWidth, 3180).
+-define(wxStyledTextCtrl_TextWidth, 3181).
+-define(wxStyledTextCtrl_GetEndAtLastLine, 3182).
+-define(wxStyledTextCtrl_TextHeight, 3183).
+-define(wxStyledTextCtrl_SetUseVerticalScrollBar, 3184).
+-define(wxStyledTextCtrl_GetUseVerticalScrollBar, 3185).
+-define(wxStyledTextCtrl_AppendText, 3186).
+-define(wxStyledTextCtrl_GetTwoPhaseDraw, 3187).
+-define(wxStyledTextCtrl_SetTwoPhaseDraw, 3188).
+-define(wxStyledTextCtrl_TargetFromSelection, 3189).
+-define(wxStyledTextCtrl_LinesJoin, 3190).
+-define(wxStyledTextCtrl_LinesSplit, 3191).
+-define(wxStyledTextCtrl_SetFoldMarginColour, 3192).
+-define(wxStyledTextCtrl_SetFoldMarginHiColour, 3193).
+-define(wxStyledTextCtrl_LineDown, 3194).
+-define(wxStyledTextCtrl_LineDownExtend, 3195).
+-define(wxStyledTextCtrl_LineUp, 3196).
+-define(wxStyledTextCtrl_LineUpExtend, 3197).
+-define(wxStyledTextCtrl_CharLeft, 3198).
+-define(wxStyledTextCtrl_CharLeftExtend, 3199).
+-define(wxStyledTextCtrl_CharRight, 3200).
+-define(wxStyledTextCtrl_CharRightExtend, 3201).
+-define(wxStyledTextCtrl_WordLeft, 3202).
+-define(wxStyledTextCtrl_WordLeftExtend, 3203).
+-define(wxStyledTextCtrl_WordRight, 3204).
+-define(wxStyledTextCtrl_WordRightExtend, 3205).
+-define(wxStyledTextCtrl_Home, 3206).
+-define(wxStyledTextCtrl_HomeExtend, 3207).
+-define(wxStyledTextCtrl_LineEnd, 3208).
+-define(wxStyledTextCtrl_LineEndExtend, 3209).
+-define(wxStyledTextCtrl_DocumentStart, 3210).
+-define(wxStyledTextCtrl_DocumentStartExtend, 3211).
+-define(wxStyledTextCtrl_DocumentEnd, 3212).
+-define(wxStyledTextCtrl_DocumentEndExtend, 3213).
+-define(wxStyledTextCtrl_PageUp, 3214).
+-define(wxStyledTextCtrl_PageUpExtend, 3215).
+-define(wxStyledTextCtrl_PageDown, 3216).
+-define(wxStyledTextCtrl_PageDownExtend, 3217).
+-define(wxStyledTextCtrl_EditToggleOvertype, 3218).
+-define(wxStyledTextCtrl_Cancel, 3219).
+-define(wxStyledTextCtrl_DeleteBack, 3220).
+-define(wxStyledTextCtrl_Tab, 3221).
+-define(wxStyledTextCtrl_BackTab, 3222).
+-define(wxStyledTextCtrl_NewLine, 3223).
+-define(wxStyledTextCtrl_FormFeed, 3224).
+-define(wxStyledTextCtrl_VCHome, 3225).
+-define(wxStyledTextCtrl_VCHomeExtend, 3226).
+-define(wxStyledTextCtrl_ZoomIn, 3227).
+-define(wxStyledTextCtrl_ZoomOut, 3228).
+-define(wxStyledTextCtrl_DelWordLeft, 3229).
+-define(wxStyledTextCtrl_DelWordRight, 3230).
+-define(wxStyledTextCtrl_LineCut, 3231).
+-define(wxStyledTextCtrl_LineDelete, 3232).
+-define(wxStyledTextCtrl_LineTranspose, 3233).
+-define(wxStyledTextCtrl_LineDuplicate, 3234).
+-define(wxStyledTextCtrl_LowerCase, 3235).
+-define(wxStyledTextCtrl_UpperCase, 3236).
+-define(wxStyledTextCtrl_LineScrollDown, 3237).
+-define(wxStyledTextCtrl_LineScrollUp, 3238).
+-define(wxStyledTextCtrl_DeleteBackNotLine, 3239).
+-define(wxStyledTextCtrl_HomeDisplay, 3240).
+-define(wxStyledTextCtrl_HomeDisplayExtend, 3241).
+-define(wxStyledTextCtrl_LineEndDisplay, 3242).
+-define(wxStyledTextCtrl_LineEndDisplayExtend, 3243).
+-define(wxStyledTextCtrl_HomeWrapExtend, 3244).
+-define(wxStyledTextCtrl_LineEndWrap, 3245).
+-define(wxStyledTextCtrl_LineEndWrapExtend, 3246).
+-define(wxStyledTextCtrl_VCHomeWrap, 3247).
+-define(wxStyledTextCtrl_VCHomeWrapExtend, 3248).
+-define(wxStyledTextCtrl_LineCopy, 3249).
+-define(wxStyledTextCtrl_MoveCaretInsideView, 3250).
+-define(wxStyledTextCtrl_LineLength, 3251).
+-define(wxStyledTextCtrl_BraceHighlight, 3252).
+-define(wxStyledTextCtrl_BraceBadLight, 3253).
+-define(wxStyledTextCtrl_BraceMatch, 3254).
+-define(wxStyledTextCtrl_GetViewEOL, 3255).
+-define(wxStyledTextCtrl_SetViewEOL, 3256).
+-define(wxStyledTextCtrl_SetModEventMask, 3257).
+-define(wxStyledTextCtrl_GetEdgeColumn, 3258).
+-define(wxStyledTextCtrl_SetEdgeColumn, 3259).
+-define(wxStyledTextCtrl_GetEdgeMode, 3260).
+-define(wxStyledTextCtrl_GetEdgeColour, 3261).
+-define(wxStyledTextCtrl_SetEdgeColour, 3262).
+-define(wxStyledTextCtrl_SearchAnchor, 3263).
+-define(wxStyledTextCtrl_SearchNext, 3264).
+-define(wxStyledTextCtrl_SearchPrev, 3265).
+-define(wxStyledTextCtrl_LinesOnScreen, 3266).
+-define(wxStyledTextCtrl_UsePopUp, 3267).
+-define(wxStyledTextCtrl_SelectionIsRectangle, 3268).
+-define(wxStyledTextCtrl_SetZoom, 3269).
+-define(wxStyledTextCtrl_GetZoom, 3270).
+-define(wxStyledTextCtrl_GetModEventMask, 3271).
+-define(wxStyledTextCtrl_SetSTCFocus, 3272).
+-define(wxStyledTextCtrl_GetSTCFocus, 3273).
+-define(wxStyledTextCtrl_SetStatus, 3274).
+-define(wxStyledTextCtrl_GetStatus, 3275).
+-define(wxStyledTextCtrl_SetMouseDownCaptures, 3276).
+-define(wxStyledTextCtrl_GetMouseDownCaptures, 3277).
+-define(wxStyledTextCtrl_SetSTCCursor, 3278).
+-define(wxStyledTextCtrl_GetSTCCursor, 3279).
+-define(wxStyledTextCtrl_SetControlCharSymbol, 3280).
+-define(wxStyledTextCtrl_GetControlCharSymbol, 3281).
+-define(wxStyledTextCtrl_WordPartLeft, 3282).
+-define(wxStyledTextCtrl_WordPartLeftExtend, 3283).
+-define(wxStyledTextCtrl_WordPartRight, 3284).
+-define(wxStyledTextCtrl_WordPartRightExtend, 3285).
+-define(wxStyledTextCtrl_SetVisiblePolicy, 3286).
+-define(wxStyledTextCtrl_DelLineLeft, 3287).
+-define(wxStyledTextCtrl_DelLineRight, 3288).
+-define(wxStyledTextCtrl_GetXOffset, 3289).
+-define(wxStyledTextCtrl_ChooseCaretX, 3290).
+-define(wxStyledTextCtrl_SetXCaretPolicy, 3291).
+-define(wxStyledTextCtrl_SetYCaretPolicy, 3292).
+-define(wxStyledTextCtrl_GetPrintWrapMode, 3293).
+-define(wxStyledTextCtrl_SetHotspotActiveForeground, 3294).
+-define(wxStyledTextCtrl_SetHotspotActiveBackground, 3295).
+-define(wxStyledTextCtrl_SetHotspotActiveUnderline, 3296).
+-define(wxStyledTextCtrl_SetHotspotSingleLine, 3297).
+-define(wxStyledTextCtrl_ParaDownExtend, 3298).
+-define(wxStyledTextCtrl_ParaUp, 3299).
+-define(wxStyledTextCtrl_ParaUpExtend, 3300).
+-define(wxStyledTextCtrl_PositionBefore, 3301).
+-define(wxStyledTextCtrl_PositionAfter, 3302).
+-define(wxStyledTextCtrl_CopyRange, 3303).
+-define(wxStyledTextCtrl_CopyText, 3304).
+-define(wxStyledTextCtrl_SetSelectionMode, 3305).
+-define(wxStyledTextCtrl_GetSelectionMode, 3306).
+-define(wxStyledTextCtrl_LineDownRectExtend, 3307).
+-define(wxStyledTextCtrl_LineUpRectExtend, 3308).
+-define(wxStyledTextCtrl_CharLeftRectExtend, 3309).
+-define(wxStyledTextCtrl_CharRightRectExtend, 3310).
+-define(wxStyledTextCtrl_HomeRectExtend, 3311).
+-define(wxStyledTextCtrl_VCHomeRectExtend, 3312).
+-define(wxStyledTextCtrl_LineEndRectExtend, 3313).
+-define(wxStyledTextCtrl_PageUpRectExtend, 3314).
+-define(wxStyledTextCtrl_PageDownRectExtend, 3315).
+-define(wxStyledTextCtrl_StutteredPageUp, 3316).
+-define(wxStyledTextCtrl_StutteredPageUpExtend, 3317).
+-define(wxStyledTextCtrl_StutteredPageDown, 3318).
+-define(wxStyledTextCtrl_StutteredPageDownExtend, 3319).
+-define(wxStyledTextCtrl_WordLeftEnd, 3320).
+-define(wxStyledTextCtrl_WordLeftEndExtend, 3321).
+-define(wxStyledTextCtrl_WordRightEnd, 3322).
+-define(wxStyledTextCtrl_WordRightEndExtend, 3323).
+-define(wxStyledTextCtrl_SetWhitespaceChars, 3324).
+-define(wxStyledTextCtrl_SetCharsDefault, 3325).
+-define(wxStyledTextCtrl_AutoCompGetCurrent, 3326).
+-define(wxStyledTextCtrl_Allocate, 3327).
+-define(wxStyledTextCtrl_FindColumn, 3328).
+-define(wxStyledTextCtrl_GetCaretSticky, 3329).
+-define(wxStyledTextCtrl_SetCaretSticky, 3330).
+-define(wxStyledTextCtrl_ToggleCaretSticky, 3331).
+-define(wxStyledTextCtrl_SetPasteConvertEndings, 3332).
+-define(wxStyledTextCtrl_GetPasteConvertEndings, 3333).
+-define(wxStyledTextCtrl_SelectionDuplicate, 3334).
+-define(wxStyledTextCtrl_SetCaretLineBackAlpha, 3335).
+-define(wxStyledTextCtrl_GetCaretLineBackAlpha, 3336).
+-define(wxStyledTextCtrl_StartRecord, 3337).
+-define(wxStyledTextCtrl_StopRecord, 3338).
+-define(wxStyledTextCtrl_SetLexer, 3339).
+-define(wxStyledTextCtrl_GetLexer, 3340).
+-define(wxStyledTextCtrl_Colourise, 3341).
+-define(wxStyledTextCtrl_SetProperty, 3342).
+-define(wxStyledTextCtrl_SetKeyWords, 3343).
+-define(wxStyledTextCtrl_SetLexerLanguage, 3344).
+-define(wxStyledTextCtrl_GetProperty, 3345).
+-define(wxStyledTextCtrl_GetStyleBitsNeeded, 3346).
+-define(wxStyledTextCtrl_GetCurrentLine, 3347).
+-define(wxStyledTextCtrl_StyleSetSpec, 3348).
+-define(wxStyledTextCtrl_StyleSetFont, 3349).
+-define(wxStyledTextCtrl_StyleSetFontAttr, 3350).
+-define(wxStyledTextCtrl_StyleSetCharacterSet, 3351).
+-define(wxStyledTextCtrl_StyleSetFontEncoding, 3352).
+-define(wxStyledTextCtrl_CmdKeyExecute, 3353).
+-define(wxStyledTextCtrl_SetMargins, 3354).
+-define(wxStyledTextCtrl_GetSelection, 3355).
+-define(wxStyledTextCtrl_PointFromPosition, 3356).
+-define(wxStyledTextCtrl_ScrollToLine, 3357).
+-define(wxStyledTextCtrl_ScrollToColumn, 3358).
+-define(wxStyledTextCtrl_SendMsg, 3359).
+-define(wxStyledTextCtrl_SetVScrollBar, 3360).
+-define(wxStyledTextCtrl_SetHScrollBar, 3361).
+-define(wxStyledTextCtrl_GetLastKeydownProcessed, 3362).
+-define(wxStyledTextCtrl_SetLastKeydownProcessed, 3363).
+-define(wxStyledTextCtrl_SaveFile, 3364).
+-define(wxStyledTextCtrl_LoadFile, 3365).
+-define(wxStyledTextCtrl_DoDragOver, 3366).
+-define(wxStyledTextCtrl_DoDropText, 3367).
+-define(wxStyledTextCtrl_GetUseAntiAliasing, 3368).
+-define(wxStyledTextCtrl_AddTextRaw, 3369).
+-define(wxStyledTextCtrl_InsertTextRaw, 3370).
+-define(wxStyledTextCtrl_GetCurLineRaw, 3371).
+-define(wxStyledTextCtrl_GetLineRaw, 3372).
+-define(wxStyledTextCtrl_GetSelectedTextRaw, 3373).
+-define(wxStyledTextCtrl_GetTextRangeRaw, 3374).
+-define(wxStyledTextCtrl_SetTextRaw, 3375).
+-define(wxStyledTextCtrl_GetTextRaw, 3376).
+-define(wxStyledTextCtrl_AppendTextRaw, 3377).
+-define(wxArtProvider_GetBitmap, 3378).
+-define(wxArtProvider_GetIcon, 3379).
+-define(wxTreeEvent_GetKeyCode, 3380).
+-define(wxTreeEvent_GetItem, 3381).
+-define(wxTreeEvent_GetKeyEvent, 3382).
+-define(wxTreeEvent_GetLabel, 3383).
+-define(wxTreeEvent_GetOldItem, 3384).
+-define(wxTreeEvent_GetPoint, 3385).
+-define(wxTreeEvent_IsEditCancelled, 3386).
+-define(wxTreeEvent_SetToolTip, 3387).
+-define(wxNotebookEvent_GetOldSelection, 3388).
+-define(wxNotebookEvent_GetSelection, 3389).
+-define(wxNotebookEvent_SetOldSelection, 3390).
+-define(wxNotebookEvent_SetSelection, 3391).
+-define(wxFileDataObject_new, 3392).
+-define(wxFileDataObject_AddFile, 3393).
+-define(wxFileDataObject_GetFilenames, 3394).
+-define(wxFileDataObject_destroy, 3395).
+-define(wxTextDataObject_new, 3396).
+-define(wxTextDataObject_GetTextLength, 3397).
+-define(wxTextDataObject_GetText, 3398).
+-define(wxTextDataObject_SetText, 3399).
+-define(wxTextDataObject_destroy, 3400).
+-define(wxBitmapDataObject_new_1_1, 3401).
+-define(wxBitmapDataObject_new_1_0, 3402).
+-define(wxBitmapDataObject_GetBitmap, 3403).
+-define(wxBitmapDataObject_SetBitmap, 3404).
+-define(wxBitmapDataObject_destroy, 3405).
+-define(wxClipboard_new, 3407).
+-define(wxClipboard_destruct, 3408).
+-define(wxClipboard_AddData, 3409).
+-define(wxClipboard_Clear, 3410).
+-define(wxClipboard_Close, 3411).
+-define(wxClipboard_Flush, 3412).
+-define(wxClipboard_GetData, 3413).
+-define(wxClipboard_IsOpened, 3414).
+-define(wxClipboard_Open, 3415).
+-define(wxClipboard_SetData, 3416).
+-define(wxClipboard_UsePrimarySelection, 3418).
+-define(wxClipboard_IsSupported, 3419).
+-define(wxClipboard_Get, 3420).
+-define(wxSpinEvent_GetPosition, 3421).
+-define(wxSpinEvent_SetPosition, 3422).
+-define(wxSplitterWindow_new_0, 3423).
+-define(wxSplitterWindow_new_2, 3424).
+-define(wxSplitterWindow_destruct, 3425).
+-define(wxSplitterWindow_Create, 3426).
+-define(wxSplitterWindow_GetMinimumPaneSize, 3427).
+-define(wxSplitterWindow_GetSashGravity, 3428).
+-define(wxSplitterWindow_GetSashPosition, 3429).
+-define(wxSplitterWindow_GetSplitMode, 3430).
+-define(wxSplitterWindow_GetWindow1, 3431).
+-define(wxSplitterWindow_GetWindow2, 3432).
+-define(wxSplitterWindow_Initialize, 3433).
+-define(wxSplitterWindow_IsSplit, 3434).
+-define(wxSplitterWindow_ReplaceWindow, 3435).
+-define(wxSplitterWindow_SetSashGravity, 3436).
+-define(wxSplitterWindow_SetSashPosition, 3437).
+-define(wxSplitterWindow_SetSashSize, 3438).
+-define(wxSplitterWindow_SetMinimumPaneSize, 3439).
+-define(wxSplitterWindow_SetSplitMode, 3440).
+-define(wxSplitterWindow_SplitHorizontally, 3441).
+-define(wxSplitterWindow_SplitVertically, 3442).
+-define(wxSplitterWindow_Unsplit, 3443).
+-define(wxSplitterWindow_UpdateSize, 3444).
+-define(wxSplitterEvent_GetSashPosition, 3445).
+-define(wxSplitterEvent_GetX, 3446).
+-define(wxSplitterEvent_GetY, 3447).
+-define(wxSplitterEvent_GetWindowBeingRemoved, 3448).
+-define(wxSplitterEvent_SetSashPosition, 3449).
+-define(wxHtmlWindow_new_0, 3450).
+-define(wxHtmlWindow_new_2, 3451).
+-define(wxHtmlWindow_AppendToPage, 3452).
+-define(wxHtmlWindow_GetOpenedAnchor, 3453).
+-define(wxHtmlWindow_GetOpenedPage, 3454).
+-define(wxHtmlWindow_GetOpenedPageTitle, 3455).
+-define(wxHtmlWindow_GetRelatedFrame, 3456).
+-define(wxHtmlWindow_HistoryBack, 3457).
+-define(wxHtmlWindow_HistoryCanBack, 3458).
+-define(wxHtmlWindow_HistoryCanForward, 3459).
+-define(wxHtmlWindow_HistoryClear, 3460).
+-define(wxHtmlWindow_HistoryForward, 3461).
+-define(wxHtmlWindow_LoadFile, 3462).
+-define(wxHtmlWindow_LoadPage, 3463).
+-define(wxHtmlWindow_SelectAll, 3464).
+-define(wxHtmlWindow_SelectionToText, 3465).
+-define(wxHtmlWindow_SelectLine, 3466).
+-define(wxHtmlWindow_SelectWord, 3467).
+-define(wxHtmlWindow_SetBorders, 3468).
+-define(wxHtmlWindow_SetFonts, 3469).
+-define(wxHtmlWindow_SetPage, 3470).
+-define(wxHtmlWindow_SetRelatedFrame, 3471).
+-define(wxHtmlWindow_SetRelatedStatusBar, 3472).
+-define(wxHtmlWindow_ToText, 3473).
+-define(wxHtmlWindow_destroy, 3474).
+-define(wxHtmlLinkEvent_GetLinkInfo, 3475).
+-define(wxSystemSettings_GetColour, 3476).
+-define(wxSystemSettings_GetFont, 3477).
+-define(wxSystemSettings_GetMetric, 3478).
+-define(wxSystemSettings_GetScreenType, 3479).
+-define(wxAuiNotebookEvent_SetSelection, 3480).
+-define(wxAuiNotebookEvent_GetSelection, 3481).
+-define(wxAuiNotebookEvent_SetOldSelection, 3482).
+-define(wxAuiNotebookEvent_GetOldSelection, 3483).
+-define(wxAuiNotebookEvent_SetDragSource, 3484).
+-define(wxAuiNotebookEvent_GetDragSource, 3485).
+-define(wxAuiManagerEvent_SetManager, 3486).
+-define(wxAuiManagerEvent_GetManager, 3487).
+-define(wxAuiManagerEvent_SetPane, 3488).
+-define(wxAuiManagerEvent_GetPane, 3489).
+-define(wxAuiManagerEvent_SetButton, 3490).
+-define(wxAuiManagerEvent_GetButton, 3491).
+-define(wxAuiManagerEvent_SetDC, 3492).
+-define(wxAuiManagerEvent_GetDC, 3493).
+-define(wxAuiManagerEvent_Veto, 3494).
+-define(wxAuiManagerEvent_GetVeto, 3495).
+-define(wxAuiManagerEvent_SetCanVeto, 3496).
+-define(wxAuiManagerEvent_CanVeto, 3497).
+-define(wxLogNull_new, 3498).
+-define(wxLogNull_destroy, 3499).
diff --git a/lib/wx/test/Makefile b/lib/wx/test/Makefile
index 71b79aa272..dfec4bb695 100644
--- a/lib/wx/test/Makefile
+++ b/lib/wx/test/Makefile
@@ -63,7 +63,7 @@ release_spec:
release_tests_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) wx.spec wx_test_lib.hrl $(ErlSrc) $(ErlTargets) $(RELSYSDIR)
- $(INSTALL_PROGRAM) wxt $(RELSYSDIR)
+ $(INSTALL_SCRIPT) wxt $(RELSYSDIR)
release_docs_spec:
diff --git a/lib/wx/test/wx_class_SUITE.erl b/lib/wx/test/wx_class_SUITE.erl
index 76df6e4a23..6f43247d74 100644
--- a/lib/wx/test/wx_class_SUITE.erl
+++ b/lib/wx/test/wx_class_SUITE.erl
@@ -137,6 +137,9 @@ treeCtrl(Config) ->
wxFrame:connect(Tree, command_tree_item_expanded),
wxFrame:connect(Tree, command_tree_item_collapsed),
wxFrame:connect(Frame, close_window),
+
+ wxTreeCtrl:editLabel(Tree, Root),
+
wx_test_lib:wx_destroy(Frame,Config).
diff --git a/lib/wx/vsn.mk b/lib/wx/vsn.mk
index 4ed22d2256..c0cc302317 100644
--- a/lib/wx/vsn.mk
+++ b/lib/wx/vsn.mk
@@ -1,9 +1 @@
-WX_VSN = 0.98.6
-
-TICKETS = OTP-8656
-
-TICKETS_0.98.5 = OTP-8330 OTP-8461 OTP-8408 OTP-8455 OTP-8462
-TICKETS_0.98.4 = OTP-8243 OTP-8250 OTP-8292
-TICKETS_0.98.3 = OTP-8138 OTP-8126 OTP-8083
-TICKETS_0.98.2 = OTP-7943
-TICKETS_0.98.1 = OTP-7875 \ No newline at end of file
+WX_VSN = 0.98.7
diff --git a/lib/xmerl/doc/src/notes.xml b/lib/xmerl/doc/src/notes.xml
index 0403fbca27..d67a622481 100644
--- a/lib/xmerl/doc/src/notes.xml
+++ b/lib/xmerl/doc/src/notes.xml
@@ -31,6 +31,25 @@
<p>This document describes the changes made to the Xmerl application.</p>
+<section><title>Xmerl 1.2.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fixed problem with hex entities in UTF-8 documents:
+ When a document was in UTF-8 encoding, xmerl_scan
+ improperly replaced hex entities by the UTF-8 bytes
+ instead of returning the character, as it does with
+ inline UTF-8 text and decimal entities. (Thanks to Paul
+ Guyot.) </p>
+ <p>
+ Own Id: OTP-8697</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Xmerl 1.2.5</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/xmerl/src/xmerl_dtd.erl b/lib/xmerl/src/xmerl_dtd.erl
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/xmerl/src/xmerl_dtd.erl
+++ /dev/null
diff --git a/lib/xmerl/src/xmerl_scan.erl b/lib/xmerl/src/xmerl_scan.erl
index 4e5cc59d8f..e2e6f95c4a 100644
--- a/lib/xmerl/src/xmerl_scan.erl
+++ b/lib/xmerl/src/xmerl_scan.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -2602,8 +2602,7 @@ scan_reference("#x" ++ T, S0) ->
%% [66] CharRef
?bump_col(1),
if hd(T) /= $; ->
- {[Ch], T2, S2} = scan_char_ref_hex(T, S, 0),
- {to_char_set(S2#xmerl_scanner.encoding,Ch),T2,S2};
+ scan_char_ref_hex(T, S, 0);
true ->
?fatal(invalid_char_ref, S)
end;
@@ -3452,14 +3451,14 @@ scan_entity_value("%" ++ T, S0, Delim, Acc, PEName,Namespace,PENesting) ->
%% {system,URI} or {public,URI}
%% Included in literal.
{ExpRef,Sx}=fetch_not_parse(Tuple,S1),
- {EntV,_,_S2} =
- scan_entity_value(ExpRef, Sx, no_delim,[],
+ {EntV, _, S5} =
+ scan_entity_value(ExpRef, Sx, no_delim,[],
PERefName,parameter,[]),
%% should do an update Write(parameter_entity)
%% so next expand_pe_reference is faster
- {EntV,_S2};
+ {string_to_char_set(S5#xmerl_scanner.encoding, EntV), S5};
ExpRef ->
- {ExpRef,S1}
+ {string_to_char_set(S1#xmerl_scanner.encoding, ExpRef) ,S1}
end,
%% single or duoble qoutes are not treated as delimeters
%% in passages "included in literal"
@@ -4020,12 +4019,12 @@ utf8_2_ucs([A|Rest]) when A < 16#80 ->
utf8_2_ucs([A|Rest]) ->
{{error,{bad_character,A}},Rest}.
-to_char_set("iso-10646-utf-1",Ch) ->
- [Ch];
-to_char_set(UTF8,Ch) when UTF8 =:= "utf-8"; UTF8 =:= undefined ->
- ucs_2_utf8(Ch);
-to_char_set(_,Ch) ->
- [Ch].
+%% to_char_set("iso-10646-utf-1",Ch) ->
+%% [Ch];
+%% to_char_set(UTF8,Ch) when UTF8 =:= "utf-8"; UTF8 =:= undefined ->
+%% ucs_2_utf8(Ch);
+%% to_char_set(_,Ch) ->
+%% [Ch].
ucs_2_utf8(Ch) when Ch < 128 ->
%% 0vvvvvvv
diff --git a/lib/xmerl/vsn.mk b/lib/xmerl/vsn.mk
index aee7546c3c..d85a57f447 100644
--- a/lib/xmerl/vsn.mk
+++ b/lib/xmerl/vsn.mk
@@ -1,130 +1 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2003-2010. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-#
-
-XMERL_VSN = 1.2.5
-
-
-TICKETS = \
- OTP-8537 \
- OTP-8599
-
-TICKETS_1.2.5 = \
- OTP-8537
-
-TICKETS_1.2.4 = \
- OTP-8343
-
-TICKETS_1.2.3 = \
- OTP-8251 \
- OTP-8252 \
- OTP-8253
-
-TICKETS_1.2.2 = \
- OTP-8213 \
- OTP-8214
-
-TICKETS_1.2.1 = \
- OTP-8084 \
- OTP-8153 \
- OTP-8156
-
-TICKETS_1.2 = \
- OTP-6635
-
-TICKETS_1.1.12 = \
- OTP-7847
-
-TICKETS_1.1.11 = \
- OTP-7736
-
-TICKETS_1.1.10 = \
- OTP-6053 \
- OTP-6873 \
- OTP-7430 \
- OTP-7473 \
- OTP-7496
-
-TICKETS_1.1.9 = \
- OTP-5998 \
- OTP-6947 \
- OTP-7288
-
-TICKETS_1.1.8 = \
- OTP-7211 \
- OTP-7214
-
-TICKETS_1.1.7 = \
- OTP-7190
-
-TICKETS_1.1.6 = \
- OTP-6773 \
- OTP-6777 \
- OTP-6877 \
- OTP-6910
-
-TICKETS_1.1.5 = \
- OTP-6720 \
- OTP-6739 \
- OTP-6752
-
-TICKETS_1.1.4 = \
- OTP-6679
-
-TICKETS_1.1.3 = \
- OTP-6599
-
-TICKETS_1.1.2 = \
- OTP-6507 \
- OTP-6460
-
-TICKETS_1.1.1 = \
- OTP-6402
-
-TICKETS_1.1 = \
- OTP-6043 \
- OTP-6099 \
- OTP-6401
-
-TICKETS_1.0.5 = \
-
-
-TICKETS_1.0.4 = \
- OTP-5599 \
- OTP-5718 \
- OTP-5734 \
- OTP-5895 \
- OTP-5902 \
- OTP-5905
-
-TICKETS_1.0.3 = \
- OTP-5587
-
-TICKETS_1.0.2 = \
- OTP-5498 \
- OTP-5500 \
- OTP-5531
-
-TICKETS_1.0.1 = \
- OTP-5268 \
- OTP-5301 \
- OTP-5407
-
-TICKETS_1.0 = \
- OTP-5174 \
-
+XMERL_VSN = 1.2.6
diff --git a/make/emd2exml.in b/make/emd2exml.in
index 17cb0a0b57..ea1085cf71 100644
--- a/make/emd2exml.in
+++ b/make/emd2exml.in
@@ -44,6 +44,7 @@
-define(DELAYED_TOC_IX, 1).
-define(DELAYED_START_IX, 2).
+-compile({no_auto_import,[error/2]}).
-mode(compile).
-export([main/1]).
diff --git a/make/otp.mk.in b/make/otp.mk.in
index 9f0486a609..6ae7c5b456 100644
--- a/make/otp.mk.in
+++ b/make/otp.mk.in
@@ -25,6 +25,11 @@
.3 .1 .fig .dvi .tex .class .java .pdf .fo .psframe .pscrop .el .elc
# ----------------------------------------------------
+# Cross Compiling
+# ----------------------------------------------------
+CROSS_COMPILING = @CROSS_COMPILING@
+
+# ----------------------------------------------------
# Common macros
# ----------------------------------------------------
DEFAULT_TARGETS = opt debug release release_docs clean docs
diff --git a/otp_build b/otp_build
index 41bce4ec42..1172592415 100755
--- a/otp_build
+++ b/otp_build
@@ -1178,7 +1178,7 @@ case "$1" in
esac ;;
primary)
echo "Primary bootstrap is under version control since R13";
- echo "Use {prepare,update,commit}_primary if you really are";
+ echo "Use update_primary if you really are";
echo "updating the primary bootstrap...";;
boot)
do_boot;;
diff --git a/system/doc/Books/src/HOWTO.txt b/system/doc/Books/src/HOWTO.txt
deleted file mode 100644
index 1fa47446e3..0000000000
--- a/system/doc/Books/src/HOWTO.txt
+++ /dev/null
@@ -1,35 +0,0 @@
-Peter H�gfeldt 2001-04-27 A
-
-HOWTO for building books for printing
--------------------------------------
-
-Note: Books are also built automatically by a daily build script.
- That is the only safe way to build books.
-
-Note: Manual handling of dependency files has been removed.
-
-1. To build a book, ug say, in pdf format with a frame, be sure
- to have a clean view, and run
-
- i) clearmake -V clean
- ii) clearmake -V depend
- iii) clearmake -V ug.frame.pdf
-
- You can build the following variants: ug.ps, ug.pdf, ug.frame.ps,
- ug.frame.pdf, ug.crop.ps, and ug.crop.pdf.
-
- To build all frame.pdf and crop.pdf books replace iii) by
-
- iii) clearmake -V release_books TESTROOT=/some/dest/dir
-
- and you will get all books in /some/dest/dir.
-
-2. To change the contents of a book you have to:
-
- i) Edit the sgml book file, e.g. ug.sgml.
-
- ii) Do the corresponding changes in the Makefile (if needed).
-
-
-
-
diff --git a/system/doc/Books/src/Makefile b/system/doc/Books/src/Makefile
deleted file mode 100644
index 9d346cb230..0000000000
--- a/system/doc/Books/src/Makefile
+++ /dev/null
@@ -1,127 +0,0 @@
-# ----------------------------------------------------
-# Copyright (C) 1997, Ericsson Telecommunications
-# Author: Lars Thorsen, Hans Nilsson
-# ----------------------------------------------------
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifeq (ug.dep,$(wildcard ug.dep))
-include ug.dep
-include database_management.dep
-include orber_ic.dep
-include basic_application.dep
-include tools.dep
-include operation_maintenance.dep
-include interfaces.dep
-include stdlib.dep
-include corba_service.dep
-endif
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-BOOKS = \
- ug \
- database_management \
- orber_ic \
- corba_service \
- basic_application \
- tools \
- operation_maintenance \
- interfaces \
- stdlib
-
-TEX_FILES = $(shell for i in $(BOOKS) ; do (echo $$i.tex); done)
-
-FRAME_CROP_PDF_FILES = $(BOOKS:%=%.frame.pdf) $(BOOKS:%=%.crop.pdf)
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-XML_FLAG_booksty = -booksty otpBOOK
-DVIPS_FLAGS += -O '19mm,32.5mm'
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-all: $(FRAME_CROP_PDF_FILES)
-
-books: all
-
-clean:
- rm -f $(TEX_FILES)
- rm -f *.psframe *.pscrop *.ps
- rm -f $(TOP_PS_FILES)
- rm -f errs core *~ $(LATEX_CLEAN)
- rm -f *.dep *.pdf
-
-dep depend:
- @for i in $(BOOKS); do \
- echo "Running docdepend for $$i ..." ; \
- docdepend $$i.xml | \
- sed s/insidecover.tex/insidecover.xml/ > $$i.dep ; \
- done
-
-# ----------------------------------------------------
-# Rules
-# ----------------------------------------------------
-.SUFFIXES: .psframe .pscrop
-
-# The following rules are for multiple suffixes, e.g. kalle.pdf,
-# kalle.frame.pdf. The order of the rules is important. Default rules
-# from otp.mk are disabled in order to get it right.
-
-%.pdf: %.ps
-
-%.ps: %.dvi
-
-%.pdf: %.dvi
-
-%.frame.ps: %.dvi
- BOOK=$@ ./make_headers
- $(DVI2PS) -frame $(DVIPS_FLAGS) -f $< > $@
-
-%.frame.pdf: %.dvi
- BOOK=$@ ./make_headers
- $(DVI2PS) -frame $(DVIPS_FLAGS) -f $< | \
- $(DISTILL) $(DISTILL_FLAGS) > $@
-
-%.crop.ps: %.dvi
- BOOK=$@ ./make_headers
- $(DVI2PS) -crop $(DVIPS_FLAGS) -f $< > $@
-
-%.crop.pdf: %.dvi
- BOOK=$@ ./make_headers
- $(DVI2PS) -crop $(DVIPS_FLAGS) -f $< | \
- $(DISTILL) $(DISTILL_FLAGS) > $@
-
-%.pdf: %.dvi
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | \
- $(DISTILL) $(DISTILL_FLAGS) > $@
-
-%.ps: %.dvi
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-%.pdf: %.dvi
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | \
- $(DISTILL) $(DISTILL_FLAGS) > $@
-
-# ----------------------------------------------------
-# Release targets
-# ----------------------------------------------------
-#
-
-ifeq ($(TESTROOT),)
-release_books: all
-
-else
-release_books: all
- $(INSTALL_DIR) $(TESTROOT)/books
- $(INSTALL_DATA) $(FRAME_CROP_PDF_FILES) $(TESTROOT)/books
-endif
-
diff --git a/system/doc/Books/src/basic_application.xml b/system/doc/Books/src/basic_application.xml
deleted file mode 100644
index 8097dafd7e..0000000000
--- a/system/doc/Books/src/basic_application.xml
+++ /dev/null
@@ -1,107 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE book SYSTEM "book.dtd">
-
-<book>
- <header titlestyle="special">
- <copyright>
- <year>2000</year>
- <year>2007</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance with the License. You should have received a copy of the
- Erlang Public License along with this software. If not, it can be
- retrieved online at http://www.erlang.org/.
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- the License for the specific language governing rights and limitations
- under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>Erlang 5.1/OTP R8 Run-Time System and Basic Applications</title>
- <prepared>Bengt Nilsson</prepared>
- <docno></docno>
- <date>2000-10-17</date>
- <rev></rev>
- </header>
- <insidecover>
- <include file="insidecover"></include>
- </insidecover>
- <pagetext>Erlang/OTP Run-Time System and Basic Applications</pagetext>
- <preamble>
- <contents level="2"></contents>
- <preface>
- <p><em>Introduction</em> <br></br>
-This documentation describes the Open
- Telecom Platform (Erlang/OTP), a middle-ware based on the Erlang
- programming language, aiming at providing time-saving and flexible
- development for robust, adaptable telecom systems.</p>
- <p><em>Organization of the Documentation</em> <br></br>
-
- The documentation is divided into eight parts:</p>
- <list type="bulleted">
- <item>Erlang 5.0/OTP R7 System Documentation, EN/LZT 1084095 R1</item>
- <item>Erlang 5.0/OTP R7 Run-Time System and Basic Applications,
- EN/LZT 108 4106 R1</item>
- <item>Erlang 5.0/OTP R7 Standard Library Application, EN/LZT 108 4107
- R1</item>
- <item>Erlang 5.0/OTP R7 Database Applications, EN/LZT 108 194 R3</item>
- <item>Erlang 5.0/OTP R7 CORBA and IDL Applications,
- EN/LZT 151 810 R2</item>
- <item>Erlang 5.0/OTP R7 Interface and Communication Applications,
- EN/LZT 108 4110 R1</item>
- <item>Erlang 5.0/OTP R7 Operation and Maintenance Applications,
- EN/LZT 108 4108 R1</item>
- <item>Erlang 5.0/OTP R7 Tool Applications, EN/LZT 108 4109 R1</item>
- </list>
- <p><em>About this Book</em> <br></br>
-This book is a collection of User's Guides for</p>
- <list type="bulleted">
- <item>ERTS</item>
- <item>SASL</item>
- </list>
- <p>and of Reference Manuals for</p>
- <list type="bulleted">
- <item>ERTS</item>
- <item>SASL</item>
- <item>Compiler</item>
- <item>Kernel</item>
- </list>
- <p>The Standard Libraries (STDLIB), which are in close
- connection with Kernel, are documented in a volume of its
- own.</p>
- <br></br>
- </preface>
- </preamble>
- <pagetext>ERTS</pagetext>
- <parts lift="no">
- <title>ERTS User's Guide</title>
- <include file="../../../../erts/erts/doc/src/part"></include>
- </parts>
- <applications>
- <include file="../../../../erts/erts/doc/src/application"></include>
- </applications>
- <pagetext>SASL</pagetext>
- <parts lift="no">
- <title>SASL User's Guide</title>
- <include file="../../../../erts/lib/sasl/doc/src/part"></include>
- </parts>
- <applications>
- <include file="../../../../erts/lib/sasl/doc/src/application"></include>
- </applications>
- <pagetext>Kernel</pagetext>
- <applications>
- <include file="../../../../erts/lib/kernel/doc/src/application_holder"></include>
- </applications>
- <pagetext>Compiler</pagetext>
- <applications>
- <include file="../../../../erts/lib/compiler/doc/src/application"></include>
- </applications>
- <pagetext>Erlang/OTP Run-Time System and Basic Applications</pagetext>
-</book>
-
diff --git a/system/doc/Books/src/corba_service.xml b/system/doc/Books/src/corba_service.xml
deleted file mode 100644
index dce2894a52..0000000000
--- a/system/doc/Books/src/corba_service.xml
+++ /dev/null
@@ -1,137 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE book SYSTEM "book.dtd">
-
-<book>
- <header titlestyle="special">
- <copyright>
- <year>2001</year>
- <year>2007</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance with the License. You should have received a copy of the
- Erlang Public License along with this software. If not, it can be
- retrieved online at http://www.erlang.org/.
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- the License for the specific language governing rights and limitations
- under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>Erlang 5.1/OTP R8 CORBA Services </title>
- <prepared></prepared>
- <docno>EN/LZT 151 ??? R1</docno>
- <date>1997-05-27</date>
- <rev></rev>
- <abbreviation></abbreviation>
- </header>
- <insidecover>
- <include file="insidecover"></include>
- </insidecover>
- <pagetext>Erlang/OTP CORBA Services</pagetext>
- <preamble>
- <contents level="2"></contents>
- <preface>
- <p><em>Introduction</em> <br></br>
-
- This documentation describes the Open
- Telecom Platform (Erlang/OTP), a middle-ware based on the Erlang
- programming language, aiming at providing time-saving and flexible
- development for robust, adaptable telecom systems.</p>
- <p><em>Organization of the Documentation</em> <br></br>
-
- The documentation is divided into eight parts:</p>
- <list type="bulleted">
- <item>Erlang 5.0/OTP R7 System Documentation, EN/LZT 1084095 R1</item>
- <item>Erlang 5.0/OTP R7 Run-Time System and Basic Applications,
- EN/LZT 108 4106 R1</item>
- <item>Erlang 5.0/OTP R7 Standard Library Application, EN/LZT 108 4107
- R1</item>
- <item>Erlang 5.0/OTP R7 Database Applications, EN/LZT 108 194 R3</item>
- <item>Erlang 5.0/OTP R7 CORBA and IDL Applications,
- EN/LZT 151 810 R2</item>
- <item>Erlang 5.0/OTP R7 Interface and Communication Applications,
- EN/LZT 108 4110 R1</item>
- <item>Erlang 5.0/OTP R7 Operation and Maintenance Applications,
- EN/LZT 108 4108 R1</item>
- <item>Erlang 5.0/OTP R7 Tool Applications, EN/LZT 108 4109 R1</item>
- </list>
- <p><em>About this Book</em> <br></br>
-</p>
- <p>This book contains documentation about the six applications in Erlang/OTP that
- implement the CORBA services.
- These applications are:</p>
- <list type="bulleted">
- <item><em>cosEvent</em>, an Erlang implementation of the
- CORBA service CosEvent.</item>
- <item><em>cosEventDomain</em>, an Erlang implementation of the
- CORBA service CosEventDomainAdmin.</item>
- <item><em>cosFileTransfer</em>, an Erlang implementation of the
- CORBA service CosFileTransfer.</item>
- <item><em>cosNotificaton</em>, an Erlang implementation of the
- CORBA service CosNotification.</item>
- <item><em>cosProperty</em>, an Erlang implementation of the
- CORBA service CosProperty.</item>
- <item><em>cosTime</em>, an Erlang implementation of the
- CORBA service CosTime.</item>
- <item><em>cosTransaction</em>, an Erlang implementation of the
- CORBA service CosTransaction.</item>
- </list>
- </preface>
- </preamble>
- <pagetext>cosEvent</pagetext>
- <parts lift="no">
- <title>cosEvent User's Guide</title>
- <include file="../../../../libraries/cosEvent/doc/src/part"></include>
- </parts>
- <applications>
- <include file="../../../../libraries/cosEvent/doc/src/application"></include>
- </applications>
- <pagetext>cosEventDomain</pagetext>
- <parts lift="no">
- <title>cosEventDomain User's Guide</title>
- <include file="../../../../libraries/cosEventDomain/doc/src/part"></include>
- </parts>
- <applications>
- <include file="../../../../libraries/cosEventDomain/doc/src/application"></include>
- </applications>
- <pagetext>cosFileTransfert</pagetext>
- <parts lift="no">
- <title>cosFileTransfer User's Guide</title>
- <include file="../../../../libraries/cosFileTransfer/doc/src/part"></include>
- </parts>
- <applications>
- <include file="../../../../libraries/cosFileTransfer/doc/src/application"></include>
- </applications>
- <pagetext>cosNotification</pagetext>
- <parts lift="no">
- <title>cosNotification User's Guide</title>
- <include file="../../../../libraries/cosNotification/doc/src/part"></include>
- </parts>
- <applications>
- <include file="../../../../libraries/cosNotification/doc/src/application"></include>
- </applications>
- <pagetext>cosTime</pagetext>
- <parts lift="no">
- <title>cosTime User's Guide</title>
- <include file="../../../../libraries/cosTime/doc/src/part"></include>
- </parts>
- <applications>
- <include file="../../../../libraries/cosTime/doc/src/application"></include>
- </applications>
- <pagetext>cosProperty</pagetext>
- <parts lift="no">
- <title>cosProperty User's Guide</title>
- <include file="../../../../libraries/cosProperty/doc/src/part"></include>
- </parts>
- <applications>
- <include file="../../../../libraries/cosProperty/doc/src/application"></include>
- </applications>
- <pagetext>Erlang/OTP CORBA Services</pagetext>
-</book>
-
diff --git a/system/doc/Books/src/database_management.xml b/system/doc/Books/src/database_management.xml
deleted file mode 100644
index 268612a990..0000000000
--- a/system/doc/Books/src/database_management.xml
+++ /dev/null
@@ -1,118 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE book SYSTEM "book.dtd">
-
-<book>
- <header titlestyle="special">
- <copyright>
- <year>1997</year>
- <year>2007</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance with the License. You should have received a copy of the
- Erlang Public License along with this software. If not, it can be
- retrieved online at http://www.erlang.org/.
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- the License for the specific language governing rights and limitations
- under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>Erlang 5.1/OTP R8 Database Applications </title>
- <prepared></prepared>
- <docno>EN/LZT 108 194 R2</docno>
- <date>1997-05-27</date>
- <rev></rev>
- <abbreviation></abbreviation>
- </header>
- <insidecover>
- <include file="insidecover"></include>
- </insidecover>
- <pagetext>Erlang/OTP Database Applications</pagetext>
- <preamble>
- <contents level="2"></contents>
- <preface>
- <p><em>Introduction</em> <br></br>
-This documentation describes the Open
- Telecom Platform (Erlang/OTP), a middle-ware based on the Erlang
- programming language, aiming at providing time-saving and flexible
- development for robust, adaptable telecom systems.</p>
- <p><em>Organization of the Documentation</em> <br></br>
-
- The documentation is divided into eight parts:</p>
- <list type="bulleted">
- <item>Erlang 5.0/OTP R7 System Documentation, EN/LZT 1084095 R1</item>
- <item>Erlang 5.0/OTP R7 Run-Time System and Basic Applications,
- EN/LZT 108 4106 R1</item>
- <item>Erlang 5.0/OTP R7 Standard Library Application, EN/LZT 108 4107
- R1</item>
- <item>Erlang 5.0/OTP R7 Database Applications, EN/LZT 108 194 R3</item>
- <item>Erlang 5.0/OTP R7 CORBA and IDL Applications,
- EN/LZT 151 810 R2</item>
- <item>Erlang 5.0/OTP R7 Interface and Communication Applications,
- EN/LZT 108 4110 R1</item>
- <item>Erlang 5.0/OTP R7 Operation and Maintenance Applications,
- EN/LZT 108 4108 R1</item>
- <item>Erlang 5.0/OTP R7 Tool Applications, EN/LZT 108 4109 R1</item>
- </list>
- <p><em>About this Book</em> <br></br>
-</p>
- <p>This book is common for the four applications in Erlang/OTP, which
- manage databases. These applications are:</p>
- <list type="bulleted">
- <item><em>Mnesia</em>; to be used when
- a continuous
- operation and soft real-time properties are required.</item>
- <item><em>Mnesia_Session</em>; to be used when the Mnesia Database
- Management
- System has to be accessed from other programming languages than
- Erlang.</item>
- <item><em>Mnemosyne</em>; to be used as a query language for the
- Mnesia Database
- Management System. </item>
- <item><em>ODBC,</em> Open DataBase Connectivity; to be used when
- various SQL
- databases will be accessed.</item>
- </list>
- </preface>
- </preamble>
- <pagetext>Mnesia</pagetext>
- <parts lift="no">
- <title>Mnesia User's Guide</title>
- <include file="../../../../libraries/mnesia/doc/src/part"></include>
- </parts>
- <applications>
- <include file="../../../../libraries/mnesia/doc/src/application"></include>
- </applications>
- <pagetext>Mnesia_Session</pagetext>
- <parts lift="no">
- <title>Mnesia_Session User's Guide</title>
- <include file="../../../../libraries/mnesia_session/doc/src/part"></include>
- </parts>
- <applications>
- <include file="../../../../libraries/mnesia_session/doc/src/application"></include>
- </applications>
- <pagetext>Mnemosyne</pagetext>
- <parts lift="no">
- <title>Mnemosyne User's Guide</title>
- <include file="../../../../libraries/mnemosyne/doc/src/part"></include>
- </parts>
- <applications>
- <include file="../../../../libraries/mnemosyne/doc/src/application"></include>
- </applications>
- <pagetext>ODBC </pagetext>
- <parts lift="no">
- <title>ODBC User's Guide</title>
- <include file="../../../../libraries/odbc/doc/src/part"></include>
- </parts>
- <applications>
- <include file="../../../../libraries/odbc/doc/src/application"></include>
- </applications>
- <pagetext>Erlang/OTP Database Applications</pagetext>
-</book>
-
diff --git a/system/doc/Books/src/frame_crop.header.src b/system/doc/Books/src/frame_crop.header.src
deleted file mode 100644
index 131045ef8d..0000000000
--- a/system/doc/Books/src/frame_crop.header.src
+++ /dev/null
@@ -1,101 +0,0 @@
-%% This PostScript file centers the page on an A4 paper and draws a
-%% crop marks. dvips is assumed.
-
-%% DEBUG
-%% /mydict 20 dict def mydict begin
-
-%% Millimeter to postscript points:
-
-/mm{ 25.4 div 72 mul }def
-
-
-%% The size of the retangle is:
-
-/papw 172 mm def
-/paph 232 mm def
-
-%% The text area size is:
-
-%%/txtw{131 mm}def
-%%/txth{285 mm}def
-
-
-%% A4 size is:
-
-/A4w 209 mm def
-/A4h 296 mm def
-
-%% Draw crop marks
-
-/mkcrop{
- 0.3 setlinewidth
- 0 0 mkonecrop
- papw 0 mkonecrop
- 0 paph mkonecrop
- papw paph mkonecrop
-} def
-
-/mkonecrop{gsave
- translate
- newpath
- 0 18 moveto
- 0 -18 lineto
- stroke
- newpath
- -18 0 moveto
- 18 0 lineto
- stroke
- grestore } def
-
-%% Draw a frame
-
-/mkframe{
- gsave
- 0 A4h paph sub moveto
- papw 0 rlineto
- 0 paph rlineto
- papw neg 0 rlineto
- 0 paph neg rlineto
- stroke
- grestore
-} def
-
-/mkmarks{mk@MARKS@} def
-
-/mkinfo{ gsave
- 72 68 moveto (Book: @BOOK@) show
- 72 60 moveto (Generated by dvips: @DATE@) show
- 72 52 moveto (Config spec: @CSFILE@) show
- 72 44 moveto (View: @VIEW@) show
- 72 36 moveto (User: @USER@) show
- 72 28 moveto (Latex: @LATEX@) show
- 72 20 moveto (@DOCBVSN@ @DOCB@) show
- 72 12 moveto (@DVIPSVSN@ @DVIPS@) show
- 288 68 moveto (Book build: @BOOKBUILD@) show
- 288 60 moveto (Build script: @BUILDSCRIPT@) show
- grestore
-} def
-
-
-%% Beginning-of-page hook (the thing called by dvips):
-
-/bop-hook{
- gsave
- /Helvetica findfont 7 scalefont setfont
- gsave
- A4w papw sub 2 div
- A4h paph sub 2 div neg
- translate
- mkmarks
- grestore
- mkinfo
- grestore
-} def
-
-%% DEBUG
-%%/bop-hook
-%%showpage
-%%end
-
-
-
diff --git a/system/doc/Books/src/insidecover.xml b/system/doc/Books/src/insidecover.xml
deleted file mode 100644
index e6b4b4206c..0000000000
--- a/system/doc/Books/src/insidecover.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE bookinsidecover SYSTEM "bookinsidecover.dtd">
-
-<bookinsidecover>
-Ericsson Utvecklings AB provides this publication ``as is'' without warranty of any kind. In no event shall Ericsson Utvecklings AB be liable for any damage arising from any defect or error in this publication. The contents of this publication is subject to revision without notice due to continued progress in design. <br></br>
- <br></br>
-Copyright &copy; 1996-2000 Ericsson Utvecklings AB. <br></br>
- <br></br>
-All rights reserved including the right of reproduction in whole or in part in any form. <br></br>
- <vfill></vfill>
- <br></br>
- <bold>Editors &amp; Layout:</bold>
-Anna Fedoriw and Bengt Nilsson <br></br>
- <bold>Written and Produced by:</bold>
-The Open Telecom Platform Project <br></br>
- <bold>Cover by:</bold>
-R&ouml;jning &amp; Co <br></br>
- <br></br>
-Fourth revised and restructured edition. <br></br>
- <br></br>
-Printed in Sweden by XBS Koncerntryck, Stockholm 2000 <br></br>
- <br></br>
- <vfill></vfill>
- <br></br>
-For more information: URL <tt>http://www.erlang.se</tt>
- <br></br>
- <br></br>
- <br></br>
-Ericsson Utvecklings AB <br></br>
-OTP Product Development <br></br>
-Box 1505 <br></br>
-SE-125 25 &Auml;LVSJ&Ouml; <br></br>
-Sweden <br></br>
-</bookinsidecover>
-
diff --git a/system/doc/Books/src/interfaces.xml b/system/doc/Books/src/interfaces.xml
deleted file mode 100644
index b225f9581a..0000000000
--- a/system/doc/Books/src/interfaces.xml
+++ /dev/null
@@ -1,144 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE book SYSTEM "book.dtd">
-
-<book>
- <header titlestyle="special">
- <copyright>
- <year>2000</year>
- <year>2007</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance with the License. You should have received a copy of the
- Erlang Public License along with this software. If not, it can be
- retrieved online at http://www.erlang.org/.
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- the License for the specific language governing rights and limitations
- under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>Erlang 5.1/OTP R8 Interface and Communication Applications</title>
- <prepared>Bengt Nilsson</prepared>
- <docno></docno>
- <date>2000-02-09</date>
- <rev></rev>
- </header>
- <insidecover>
- <include file="insidecover"></include>
- </insidecover>
- <pagetext>Erlang/OTP Interface and Communication </pagetext>
- <preamble>
- <contents level="2"></contents>
- <preface>
- <p><em>Introduction</em> <br></br>
-This documentation describes the Open
- Telecom Platform (Erlang/OTP), a middle-ware based on the Erlang
- programming language, aiming at providing time-saving and flexible
- development for robust, adaptable telecom systems.</p>
- <p><em>Organization of the Documentation</em> <br></br>
-
- The documentation is divided into eight parts:</p>
- <list type="bulleted">
- <item>Erlang 5.0/OTP R7 System Documentation, EN/LZT 1084095 R1</item>
- <item>Erlang 5.0/OTP R7 Run-Time System and Basic Applications,
- EN/LZT 108 4106 R1</item>
- <item>Erlang 5.0/OTP R7 Standard Library Application, EN/LZT 108 4107
- R1</item>
- <item>Erlang 5.0/OTP R7 Database Applications, EN/LZT 108 194 R3</item>
- <item>Erlang 5.0/OTP R7 CORBA and IDL Applications,
- EN/LZT 151 810 R2</item>
- <item>Erlang 5.0/OTP R7 Interface and Communication Applications,
- EN/LZT 108 4110 R1</item>
- <item>Erlang 5.0/OTP R7 Operation and Maintenance Applications,
- EN/LZT 108 4108 R1</item>
- <item>Erlang 5.0/OTP R7 Tool Applications, EN/LZT 108 4109 R1</item>
- </list>
- <p><em>About this Book</em> <br></br>
-</p>
- <p>This book is a collection of the documentation of following applications:</p>
- <list type="bulleted">
- <item>Asn1</item>
- <item>Comet</item>
- <item>Crypto</item>
- <item>Erl_Interface</item>
- <item>GS</item>
- <item>Inets</item>
- <item>Jinterface</item>
- <item>Megaco</item>
- <item>SSL</item>
- </list>
- </preface>
- </preamble>
- <pagetext>Asn1</pagetext>
- <parts lift="yes">
- <title>Asn1 User's Guide</title>
- <include file="../../../../erts/lib/asn1/doc/src/part"></include>
- </parts>
- <applications>
- <include file="../../../../erts/lib/asn1/doc/src/application"></include>
- </applications>
- <pagetext>Comet </pagetext>
- <parts lift="no">
- <title>Comet User's Guide</title>
- <include file="../../../../erts/lib/comet/doc/src/users_guide"></include>
- </parts>
- <applications>
- <include file="../../../../erts/lib/comet/doc/src/refman"></include>
- </applications>
- <pagetext>Crypto</pagetext>
- <applications>
- <include file="../../../../erts/lib/crypto/doc/src/refman"></include>
- </applications>
- <pagetext>Erl_Interface</pagetext>
- <parts lift="yes">
- <title>Erl_Interface User's Guide</title>
- <include file="../../../../erts/lib/erl_interface/doc/src/part_erl_interface"></include>
- </parts>
- <applications>
- <include file="../../../../erts/lib/erl_interface/doc/src/application_erl_interface"></include>
- </applications>
- <pagetext>GS</pagetext>
- <parts lift="no">
- <title>GS User's Guide</title>
- <include file="../../../../erts/lib/gs/doc/src/part"></include>
- </parts>
- <applications>
- <include file="../../../../erts/lib/gs/doc/src/application"></include>
- </applications>
- <pagetext>Inets</pagetext>
- <applications>
- <include file="../../../../libraries/inets/doc/src/application"></include>
- </applications>
- <pagetext>Jinterface </pagetext>
- <parts lift="yes">
- <title>Jinterface User's Guide</title>
- <include file="../../../../erts/lib/jinterface/doc/src/part"></include>
- </parts>
- <applications>
- <include file="../../../../erts/lib/jinterface/doc/src/application"></include>
- </applications>
- <pagetext>Megaco</pagetext>
- <parts lift="no">
- <title>Megaco User's Guide</title>
- <include file="../../../../erts/lib/megaco/doc/src/part"></include>
- </parts>
- <applications>
- <include file="../../../../erts/lib/megaco/doc/src/application"></include>
- </applications>
- <pagetext>SSL </pagetext>
- <parts lift="yes">
- <title>SSL Users Guide</title>
- <include file="../../../../erts/lib/ssl/doc/src/part"></include>
- </parts>
- <applications>
- <include file="../../../../erts/lib/ssl/doc/src/refman"></include>
- </applications>
- <pagetext>Erlang/OTP Interface and Communication </pagetext>
-</book>
-
diff --git a/system/doc/Books/src/make_headers b/system/doc/Books/src/make_headers
deleted file mode 100755
index 0ec7aca632..0000000000
--- a/system/doc/Books/src/make_headers
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/sh
-#
-# Make Postscript header files (frame and crop marks)
-#
-# From environment: BOOK CSFILE USER BOOKBUILD
-
-DATE=`date`
-VIEW=`cleartool pwv -s -set`
-LATEX=`which latex`
-DVIPSVSN=`dvips -version`
-DVIPS=`which dvips`
-DOCBVSN=`docb_transform -version`
-DOCB=`which docb_transform`
-for marks in frame crop; do
- sed -e "s/@DATE@/$DATE/g" \
- -e "s/@BOOK@/$BOOK/g" \
- -e "s/@MARKS@/$marks/g" \
- -e "s;@CSFILE@;$CSFILE;g" \
- -e "s/@VIEW@/$VIEW/g" \
- -e "s/@USER@/$USER/g" \
- -e "s;@LATEX@;$LATEX;g" \
- -e "s;@DVIPSVSN@;$DVIPSVSN;g" \
- -e "s;@DVIPS@;$DVIPS;g" \
- -e "s/@DOCBVSN@/$DOCBVSN/g" \
- -e "s;@DOCB@;$DOCB;g" \
- -e "s;@BOOKBUILD@;$BOOKBUILD;g" \
- -e "s;@BUILDSCRIPT@;$BUILDSCRIPT;g" \
- frame_crop.header.src > $marks.header
-done
-
diff --git a/system/doc/Books/src/operation_maintenance.xml b/system/doc/Books/src/operation_maintenance.xml
deleted file mode 100644
index 41bdd3dff7..0000000000
--- a/system/doc/Books/src/operation_maintenance.xml
+++ /dev/null
@@ -1,94 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE book SYSTEM "book.dtd">
-
-<book>
- <header titlestyle="special">
- <copyright>
- <year>2000</year>
- <year>2007</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance with the License. You should have received a copy of the
- Erlang Public License along with this software. If not, it can be
- retrieved online at http://www.erlang.org/.
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- the License for the specific language governing rights and limitations
- under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>Erlang 5.1/OTP R8 Operation and Maintenance Applications</title>
- <prepared>Bengt Nilsson</prepared>
- <docno></docno>
- <date>2000-02-09</date>
- <rev></rev>
- </header>
- <insidecover>
- <include file="insidecover"></include>
- </insidecover>
- <pagetext>Erlang/OTP Operation and Maintenance</pagetext>
- <preamble>
- <contents level="2"></contents>
- <preface>
- <p><em>Introduction</em> <br></br>
-This documentation describes the Open
- Telecom Platform (Erlang/OTP), a middle-ware based on the Erlang
- programming language, aiming at providing time-saving and flexible
- development for robust, adaptable telecom systems.</p>
- <p><em>Organization of the Documentation</em> <br></br>
-the documentation is
- divided into eight parts:</p>
- <list type="bulleted">
- <item>Erlang 5.0/OTP R7 System Documentation, EN/LZT 1084095 R1</item>
- <item>Erlang 5.0/OTP R7 Run-Time System and Basic Applications,
- EN/LZT 108 4106 R1</item>
- <item>Erlang 5.0/OTP R7 Standard Library Application, EN/LZT 108 4107 R1</item>
- <item>Erlang 5.0/OTP R7 Database Applications, EN/LZT 108 194 R3</item>
- <item>Erlang 5.0/OTP R7 CORBA and IDL Applications,
- EN/LZT 151 810 R2</item>
- <item>Erlang 5.0/OTP R7 Interface and Communication Applications,
- EN/LZT 108 4110 R1</item>
- <item>Erlang 5.0/OTP R7 Operation and Maintenance Applications,
- EN/LZT 108 4108 R1</item>
- <item>Erlang 5.0/OTP R7 Tool Applications, EN/LZT 108 4109 R1</item>
- </list>
- <p><em>About this Book</em> <br></br>
-
- This book is a collection of Erlang application used during Operation and Maintenance. The following applications are covered:</p>
- <list type="bulleted">
- <item>EVA</item>
- <item>OS_Mon </item>
- <item>SNMP</item>
- </list>
- </preface>
- </preamble>
- <pagetext>EVA</pagetext>
- <parts lift="no">
- <title>EVA User's Guide</title>
- <include file="../../../../libraries/eva/doc/src/users_guide"></include>
- </parts>
- <applications>
- <include file="../../../../libraries/eva/doc/src/refman"></include>
- <include file="../../../../libraries/eva/doc/src/refman_snmp"></include>
- </applications>
- <pagetext>OS_Mon</pagetext>
- <applications>
- <include file="../../../../erts/lib/os_mon/doc/src/application"></include>
- </applications>
- <pagetext>SNMP</pagetext>
- <parts lift="no">
- <title>SNMP User's Guide</title>
- <include file="../../../../libraries/snmp/doc/src/part"></include>
- </parts>
- <applications>
- <include file="../../../../libraries/snmp/doc/src/application"></include>
- </applications>
- <pagetext>Erlang/OTP Operation and Maintenance</pagetext>
-</book>
-
diff --git a/system/doc/Books/src/orber_ic.xml b/system/doc/Books/src/orber_ic.xml
deleted file mode 100644
index 16eb076dc7..0000000000
--- a/system/doc/Books/src/orber_ic.xml
+++ /dev/null
@@ -1,112 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE book SYSTEM "book.dtd">
-
-<book>
- <header titlestyle="special">
- <copyright>
- <year>1999</year>
- <year>2007</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance with the License. You should have received a copy of the
- Erlang Public License along with this software. If not, it can be
- retrieved online at http://www.erlang.org/.
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- the License for the specific language governing rights and limitations
- under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>Erlang 5.1/OTP R8 CORBA and IDL Applications </title>
- <prepared></prepared>
- <docno>EN/LZT 151 810 R1</docno>
- <date>1997-05-27</date>
- <rev></rev>
- <abbreviation></abbreviation>
- </header>
- <insidecover>
- <include file="insidecover"></include>
- </insidecover>
- <pagetext>Erlang/OTP CORBA and IDL</pagetext>
- <preamble>
- <contents level="2"></contents>
- <preface>
- <p><em>Introduction</em> <br></br>
-
- This documentation describes the Open
- Telecom Platform (Erlang/OTP), a middle-ware based on the Erlang
- programming language, aiming at providing time-saving and flexible
- development for robust, adaptable telecom systems.</p>
- <p><em>Organization of the Documentation</em> <br></br>
-
- The documentation is divided into eight parts:</p>
- <list type="bulleted">
- <item>Erlang 5.0/OTP R7 System Documentation, EN/LZT 1084095 R1</item>
- <item>Erlang 5.0/OTP R7 Run-Time System and Basic Applications,
- EN/LZT 108 4106 R1</item>
- <item>Erlang 5.0/OTP R7 Standard Library Application, EN/LZT 108 4107
- R1</item>
- <item>Erlang 5.0/OTP R7 Database Applications, EN/LZT 108 194 R3</item>
- <item>Erlang 5.0/OTP R7 CORBA and IDL Applications,
- EN/LZT 151 810 R2</item>
- <item>Erlang 5.0/OTP R7 Interface and Communication Applications,
- EN/LZT 108 4110 R1</item>
- <item>Erlang 5.0/OTP R7 Operation and Maintenance Applications,
- EN/LZT 108 4108 R1</item>
- <item>Erlang 5.0/OTP R7 Tool Applications, EN/LZT 108 4109 R1</item>
- </list>
- <p><em>About this Book</em> <br></br>
-</p>
- <p>This book contains documentation about the six applications in Erlang/OTP that
- implement the CORBA standard.
- These applications are:</p>
- <list type="bulleted">
- <item>
- <p><em>IC</em>, a compiler for OMG Interface Definition
- Language (IDL).
- The OMG IDL is used for
- language-independent interface specifications.</p>
- <p>The compiler
- is capable of producing;</p>
- <list type="bulleted">
- <item>Erlang stub/skeleton code for CORBA (default behavior)</item>
- <item>Erlang stub/skeleton code for OTP generic servers</item>
- <item>C stub/skeleton code for OTP generic servers</item>
- <item>Java stub/skeleton code for OTP generic servers</item>
- <item>Erlang code for module interfaces</item>
- </list>
- </item>
- <item><em>Orber</em>, which is an Object Request Broker that can be
- used for
- accessing distributed services in an
- soft real-time environment. It is especially useful for applications
- that use a heterogeneous
- language environments.</item>
- </list>
- </preface>
- </preamble>
- <pagetext>IC</pagetext>
- <parts lift="no">
- <title>IC User's Guide </title>
- <include file="../../../../libraries/ic/doc/src/part"></include>
- </parts>
- <applications>
- <include file="../../../../libraries/ic/doc/src/application"></include>
- </applications>
- <pagetext>Orber</pagetext>
- <parts lift="no">
- <title>Orber User's Guide</title>
- <include file="../../../../libraries/orber/doc/src/part"></include>
- </parts>
- <applications>
- <include file="../../../../libraries/orber/doc/src/application"></include>
- </applications>
- <pagetext>Erlang/OTP CORBA and IDL</pagetext>
-</book>
-
diff --git a/system/doc/Books/src/stdlib.xml b/system/doc/Books/src/stdlib.xml
deleted file mode 100644
index 31ea0d6962..0000000000
--- a/system/doc/Books/src/stdlib.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE book SYSTEM "book.dtd">
-
-<book>
- <header titlestyle="special">
- <copyright>
- <year>2000</year>
- <year>2007</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance with the License. You should have received a copy of the
- Erlang Public License along with this software. If not, it can be
- retrieved online at http://www.erlang.org/.
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- the License for the specific language governing rights and limitations
- under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>Erlang 5.1/OTP R8 Standard Library Application</title>
- <prepared>Bengt Nilsson</prepared>
- <docno></docno>
- <date>2000-05-30</date>
- <rev></rev>
- </header>
- <insidecover>
- <include file="insidecover"></include>
- </insidecover>
- <pagetext>Erlang/OTP Standard Library Application</pagetext>
- <preamble>
- <contents level="2"></contents>
- <preface>
- <p><em>Introduction</em> <br></br>
-This documentation describes the Open
- Telecom Platform (Erlang/OTP), a middle-ware based on the Erlang
- programming language, aiming at providing time-saving and flexible
- development for robust, adaptable telecom systems.</p>
- <p><em>Organization of the Documentation</em> <br></br>
-
- The documentation is divided into eight parts:</p>
- <list type="bulleted">
- <item>Erlang 5.0/OTP R7 System Documentation, EN/LZT 1084095 R1</item>
- <item>Erlang 5.0/OTP R7 Run-Time System and Basic Applications,
- EN/LZT 108 4106 R1</item>
- <item>Erlang 5.0/OTP R7 Standard Library Application, EN/LZT 108 4107
- R1</item>
- <item>Erlang 5.0/OTP R7 Database Applications, EN/LZT 108 194 R3</item>
- <item>Erlang 5.0/OTP R7 CORBA and IDL Applications,
- EN/LZT 151 810 R2</item>
- <item>Erlang 5.0/OTP R7 Interface and Communication Applications,
- EN/LZT 108 4110 R1</item>
- <item>Erlang 5.0/OTP R7 Operation and Maintenance Applications,
- EN/LZT 108 4108 R1</item>
- <item>Erlang 5.0/OTP R7 Tool Applications, EN/LZT 108 4109 R1</item>
- </list>
- <p><em>About this Book</em> <br></br>
-</p>
- <p>This book describes all standard libraries in Erlang/OTP.
- It contains modules for manipulating lists, strings, and files etc.
- </p>
- </preface>
- </preamble>
- <applications>
- <include file="../../../../erts/lib/stdlib/doc/src/application"></include>
- </applications>
-</book>
-
diff --git a/system/doc/Books/src/tools.xml b/system/doc/Books/src/tools.xml
deleted file mode 100644
index 9d7bf45f31..0000000000
--- a/system/doc/Books/src/tools.xml
+++ /dev/null
@@ -1,139 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE book SYSTEM "book.dtd">
-
-<book>
- <header titlestyle="special">
- <copyright>
- <year>2000</year>
- <year>2007</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance with the License. You should have received a copy of the
- Erlang Public License along with this software. If not, it can be
- retrieved online at http://www.erlang.org/.
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- the License for the specific language governing rights and limitations
- under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>Erlang 5.1/OTP R8 Tool Applications</title>
- <prepared>Bengt Nilsson</prepared>
- <docno></docno>
- <date>2000-02-09</date>
- <rev></rev>
- </header>
- <insidecover>
- <include file="insidecover"></include>
- </insidecover>
- <pagetext>Erlang/OTP Tools</pagetext>
- <preamble>
- <contents level="1"></contents>
- <preface>
- <p><em>Introduction</em> <br></br>
-This documentation describes the Open
- Telecom Platform (Erlang/OTP), a middle-ware based on the Erlang
- programming language, aiming at providing time-saving and flexible
- development for robust, adaptable telecom systems.</p>
- <p><em>Organization of the Documentation</em> <br></br>
-
- The documentation is divided into eight parts:</p>
- <list type="bulleted">
- <item>Erlang 5.0/OTP R7 System Documentation, EN/LZT 1084095 R1</item>
- <item>Erlang 5.0/OTP R7 Run-Time System and Basic Applications,
- EN/LZT 108 4106 R1</item>
- <item>Erlang 5.0/OTP R7 Standard Library Application,
- EN/LZT 108 4107 R1</item>
- <item>Erlang 5.0/OTP R7 Database Applications, EN/LZT 108 194 R3</item>
- <item>Erlang 5.0/OTP R7 CORBA and IDL Applications,
- EN/LZT 151 810 R2</item>
- <item>Erlang 5.0/OTP R7 Interface and Communication Applications,
- EN/LZT 108 4110 R1</item>
- <item>Erlang 5.0/OTP R7 Operation and Maintenance Applications,
- EN/LZT 108 4108 R1</item>
- <item>Erlang 5.0/OTP R7 Tool Applications, EN/LZT 108 4109 R1</item>
- </list>
- <p><em>About this Book</em> <br></br>
-This book contains User's Guides
- and Reference Manuals
- for the following applications:</p>
- <list type="bulleted">
- <item>Appmon</item>
- <item>Debugger</item>
- <item>Pman</item>
- <item>Toolbar</item>
- <item>Tools</item>
- <item>TV</item>
- </list>
- <p>For the following applications, only Reference Manuals are available:</p>
- <list type="bulleted">
- <item>Parsetools</item>
- <item>Runtime_Tools</item>
- </list>
- </preface>
- </preamble>
- <pagetext>Appmon</pagetext>
- <parts lift="yes">
- <title>Appmon User's Guide</title>
- <include file="../../../../libraries/appmon/doc/src/part"></include>
- </parts>
- <applications>
- <include file="../../../../libraries/appmon/doc/src/application"></include>
- </applications>
- <pagetext>Debugger</pagetext>
- <parts lift="yes">
- <title>Debugger User's Guide</title>
- <include file="../../../../tools/debugger/doc/src/part"></include>
- </parts>
- <applications>
- <include file="../../../../tools/debugger/doc/src/application"></include>
- </applications>
- <pagetext>Pman</pagetext>
- <parts lift="yes">
- <title>Pman User's Guide</title>
- <include file="../../../../tools/pman/doc/src/part"></include>
- </parts>
- <applications>
- <include file="../../../../tools/pman/doc/src/application"></include>
- </applications>
- <pagetext>Toolbar</pagetext>
- <parts lift="yes">
- <title>Toolbar User's Guide</title>
- <include file="../../../../tools/toolbar/doc/src/part"></include>
- </parts>
- <applications>
- <include file="../../../../tools/toolbar/doc/src/application"></include>
- </applications>
- <pagetext>Tools</pagetext>
- <parts lift="no">
- <title>Tools User's Guide</title>
- <include file="../../../../tools/tools/doc/src/part"></include>
- </parts>
- <applications>
- <include file="../../../../tools/tools/doc/src/application"></include>
- </applications>
- <pagetext>TV</pagetext>
- <parts lift="yes">
- <title>TV User's Guide</title>
- <include file="../../../../tools/tv/doc/src/part"></include>
- </parts>
- <applications>
- <include file="../../../../tools/tv/doc/src/application"></include>
- </applications>
- <pagetext>Parsetools</pagetext>
- <applications>
- <include file="../../../../tools/parsetools/doc/src/application"></include>
- </applications>
- <pagetext>Runtime_Tools</pagetext>
- <applications>
- <include file="../../../../tools/runtime_tools/doc/src/refman"></include>
- </applications>
- <pagetext>Erlang/OTP Tools</pagetext>
-</book>
-
diff --git a/system/doc/Books/src/ug.xml b/system/doc/Books/src/ug.xml
deleted file mode 100644
index 15b3dc0a31..0000000000
--- a/system/doc/Books/src/ug.xml
+++ /dev/null
@@ -1,127 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE book SYSTEM "book.dtd">
-
-<book>
- <header titlestyle="special">
- <copyright>
- <year>1997</year>
- <year>2007</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance with the License. You should have received a copy of the
- Erlang Public License along with this software. If not, it can be
- retrieved online at http://www.erlang.org/.
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- the License for the specific language governing rights and limitations
- under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>Erlang 5.1/OTP R8 System Documentation</title>
- <prepared></prepared>
- <docno>EN/LZT 151 247 R2</docno>
- <date></date>
- <rev></rev>
- </header>
- <insidecover>
- <include file="insidecover"></include>
- </insidecover>
- <pagetext>Erlang/OTP System Documentation</pagetext>
- <preamble>
- <contents level="2"></contents>
- <preface>
- <p><em>Introduction</em> <br></br>
-This documentation describes the Open
- Telecom Platform (Erlang/OTP), a middle-ware based on the Erlang
- programming language, aiming at providing time-saving and flexible
- development for robust, adaptable telecom systems.</p>
- <p><em>Organization of the Documentation</em> <br></br>
-
- The documentation is divided into eight parts:</p>
- <list type="bulleted">
- <item>Erlang 5.0/OTP R7 System Documentation, EN/LZT 1084095 R1</item>
- <item>Erlang 5.0/OTP R7 Run-Time System and Basic Applications,
- EN/LZT 108 4106 R1</item>
- <item>Erlang 5.0/OTP R7 Standard Library Application, EN/LZT 108 4107
- R1</item>
- <item>Erlang 5.0/OTP R7 Database Applications, EN/LZT 108 194 R3</item>
- <item>Erlang 5.0/OTP R7 CORBA and IDL Applications,
- EN/LZT 151 810 R2</item>
- <item>Erlang 5.0/OTP R7 Interface and Communication Applications,
- EN/LZT 108 4110 R1</item>
- <item>Erlang 5.0/OTP R7 Operation and Maintenance Applications,
- EN/LZT 108 4108 R1</item>
- <item>Erlang 5.0/OTP R7 Tool Applications, EN/LZT 108 4109 R1</item>
- </list>
- <p><em>About this Book</em> <br></br>
- This book is the starting point of the documentation and contains information about the Erlang programming language and runtime system, the OTP design principles, and how to install and configure Erlang/OTP.</p>
- <list type="bulleted">
- <item>Chapter 1: Introduction</item>
- <item>Chapter 2: "Getting Started with Erlang" gives an introduction to the Erlang runtime system and to tools such as Compiler and Debugger.</item>
- <item>Chapter 3: "OTP Design Principles" describes a way to structure Erlang code in terms of applications and supervision trees. The standard behaviors are described and examples illustrate how to apply these behaviors to typical applications.</item>
- <item>Chapter 4: "System Principles" describes the strategies
- and options, which are available to start an Erlang/OTP system. </item>
- <item>Chapter 5: "Operation and Management Principles" describes the model for operation and maintenance of sub-systems.</item>
- <item>Chapter 6: "Installation Guide"gives guidelines on how to install Erlang/OTP on UNIX or Windows.</item>
- <item>Chapter 7: "Embedded Systems" is a supplement to "Installation Guide", It describes issues that are specific for running Erlang/OTP on an embedded system.</item>
- <item>Chapter 8: "Erlang Extensions Since 4.4" lists all extensions to the Erlang programming languages since the latest version of the book <em>Concurrent Programming in ERLANG</em>.</item>
- <item>Chapter 9: "Interoperability Tutorial" gives an orientation of the different
- interoperability mechanisms, which can be used when integrating an
- Erlang program with a program written in an other programming language.</item>
- </list>
- </preface>
- </preamble>
- <pagetext>Introduction</pagetext>
- <parts lift="yes">
- <title>Introduction</title>
- <include file="../../system_architecture_intro/part"></include>
- </parts>
- <pagetext>Getting Started with Erlang</pagetext>
- <parts lift="yes">
- <title>Getting Started with Erlang</title>
- <include file="../../getting_started/part"></include>
- </parts>
- <pagetext>Design Principles</pagetext>
- <parts lift="no">
- <title>OTP Design Principles</title>
- <include file="../../design_principles/part"></include>
- </parts>
- <pagetext>System Principles</pagetext>
- <parts lift="yes">
- <title>System Principles</title>
- <include file="../../system_principles/part"></include>
- </parts>
- <pagetext>Operation and Management Principles</pagetext>
- <parts lift="yes">
- <title>Operation and Management Principles</title>
- <include file="../../oam/part"></include>
- </parts>
- <pagetext>Installation Guide</pagetext>
- <parts lift="no">
- <title>Installation Guide</title>
- <include file="../../../../system/doc/installation_guide/part"></include>
- </parts>
- <pagetext>Embedded System</pagetext>
- <parts lift="no">
- <title>Embedded System</title>
- <include file="../../../../system/doc/embedded/part"></include>
- </parts>
- <pagetext>Erlang Extensions since 4.4</pagetext>
- <parts lift="no">
- <title>Erlang Extensions since 4.4</title>
- <include file="../../../../system/doc/extensions/part"></include>
- </parts>
- <pagetext>Interoperability Tutorial</pagetext>
- <parts lift="no">
- <title>Interoperability Tutorial</title>
- <include file="../../tutorial/part"></include>
- </parts>
- <pagetext>Erlang/OTP System Documentation</pagetext>
-</book>
-
diff --git a/system/doc/reference_manual/typespec.xml b/system/doc/reference_manual/typespec.xml
index a3660713e4..f08639f9a1 100755
--- a/system/doc/reference_manual/typespec.xml
+++ b/system/doc/reference_manual/typespec.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2009</year>
+ <year>2003</year><year>2010</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,29 +32,24 @@
<section>
<title>Introduction of Types</title>
<p>
- Although Erlang is a dynamically typed language this section describes
- an extension to the Erlang language for declaring sets of Erlang terms
- to form a particular type, effectively forming a specific sub-type of the
- set of all Erlang terms.
+ Erlang is a dynamically typed language. Still, it comes with a
+ language extension for declaring sets of Erlang terms to form a
+ particular type, effectively forming a specific sub-type of the set
+ of all Erlang terms.
</p>
<p>
- Subsequently, these types can be used to specify types of record fields
- and the argument and return types of functions.
+ Subsequently, these types can be used to specify types of record fields
+ and the argument and return types of functions.
</p>
<p>
- Type information can be used to document function interfaces,
- provide more information for bug detection tools such as <c>Dialyzer</c>,
- and can be exploited by documentation tools such as <c>Edoc</c> for
- generating program documentation of various forms.
- It is expected that the type language described in this document will
- supersede and replace the purely comment-based <c>@type</c> and
+ Type information can be used to document function interfaces,
+ provide more information for bug detection tools such as <c>Dialyzer</c>,
+ and can be exploited by documentation tools such as <c>Edoc</c> for
+ generating program documentation of various forms.
+ It is expected that the type language described in this document will
+ supersede and replace the purely comment-based <c>@type</c> and
<c>@spec</c> declarations used by <c>Edoc</c>.
</p>
- <warning>
- The syntax and semantics described here is still preliminary and might be
- slightly changed and extended before it becomes officially supported.
- The plan is that this will happen in R14B.
- </warning>
</section>
<section>
<marker id="syntax"></marker>
@@ -96,7 +91,7 @@ Type :: any() %% The top type, the set of all Erlang terms.
| none() %% The bottom type, contains no terms.
| pid()
| port()
- | ref()
+ | reference()
| [] %% nil
| Atom
| Binary
@@ -139,326 +134,334 @@ Tuple :: tuple() %% stands for a tuple of any size
TList :: Type
| Type, TList
]]></pre>
- <p>
- Because lists are commonly used, they have shorthand type notations.
- The type <c>list(T)</c> has the shorthand <c>[T]</c>. The shorthand <c>[T,...]</c> stands for
- the set of non-empty proper lists whose elements are of type <c>T</c>.
- The only difference between the two shorthands is that <c>[T]</c> may be an
- empty list but <c>[T,...]</c> may not.
- </p>
- <p>
- Notice that the shorthand for <c>list()</c>, i.e. the list of elements of unknown type,
- is <c>[_]</c> (or <c>[any()]</c>), not <c>[]</c>.
- The notation <c>[]</c> specifies the singleton type for the empty list.
- </p>
- <p>
- For convenience, the following types are also built-in.
- They can be thought as predefined aliases for the type unions also shown in
- the table. (Some type unions below slightly abuse the syntax of types.)
- </p>
- <table>
- <row>
- <cell><b>Built-in type</b></cell><cell><b>Stands for</b></cell>
- </row>
- <row>
- <cell><c>term()</c></cell><cell><c>any()</c></cell>
- </row>
- <row>
- <cell><c>bool()</c></cell><cell><c>'false' | 'true'</c></cell>
- </row>
- <row>
- <cell><c>byte()</c></cell><cell><c>0..255</c></cell>
- </row>
- <row>
- <cell><c>char()</c></cell><cell><c>0..16#10ffff</c></cell>
- </row>
- <row>
- <cell><c>non_neg_integer()</c></cell><cell><c>0..</c></cell>
- </row>
- <row>
- <cell><c>pos_integer()</c></cell><cell><c>1..</c></cell>
- </row>
- <row>
- <cell><c>neg_integer()</c></cell><cell><c>..-1</c></cell>
- </row>
- <row>
- <cell><c>number()</c></cell><cell><c>integer() | float()</c></cell>
- </row>
- <row>
- <cell><c>list()</c></cell><cell><c>[any()]</c></cell>
- </row>
- <row>
- <cell><c>maybe_improper_list()</c></cell><cell><c>maybe_improper_list(any(), any())</c></cell>
- </row>
- <row>
- <cell><c>maybe_improper_list(T)</c></cell><cell><c>maybe_improper_list(T, any())</c></cell>
- </row>
- <row>
- <cell><c>string()</c></cell><cell><c>[char()]</c></cell>
- </row>
- <row>
- <cell><c>nonempty_string()</c></cell><cell><c>[char(),...]</c></cell>
- </row>
- <row>
- <cell><c>iolist()</c></cell><cell><c>maybe_improper_list(
-char() | binary() | iolist(), binary() | [])</c></cell>
- </row>
- <row>
- <cell><c>module()</c></cell><cell><c>atom()</c></cell>
- </row>
- <row>
- <cell><c>mfa()</c></cell><cell><c>{atom(),atom(),byte()}</c></cell>
- </row>
- <row>
- <cell><c>node()</c></cell><cell><c>atom()</c></cell>
- </row>
- <row>
- <cell><c>timeout()</c></cell><cell><c>'infinity' | non_neg_integer()</c></cell>
- </row>
- <row>
- <cell><c>no_return()</c></cell><cell><c>none()</c></cell>
- </row>
- </table>
-
- <p>
- Users are not allowed to define types with the same names as the predefined or
- built-in ones.
- This is checked by the compiler and its violation results in a compilation
- error.
- (For bootstrapping purposes, it can also result to just a warning if this
- involves a built-in type which has just been introduced.)
- </p>
- <note>
- The following built-in list types also exist,
- but they are expected to be rarely used. Hence, they have long names:
- </note>
- <pre>
+ <p>
+ Because lists are commonly used, they have shorthand type notations.
+ The type <c>list(T)</c> has the shorthand <c>[T]</c>.
+ The shorthand <c>[T,...]</c> stands for
+ the set of non-empty proper lists whose elements are of type <c>T</c>.
+ The only difference between the two shorthands is that <c>[T]</c> may be an
+ empty list but <c>[T,...]</c> may not.
+ </p>
+ <p>
+ Notice that the shorthand for <c>list()</c>, i.e. the list of
+ elements of unknown type, is <c>[_]</c> (or <c>[any()]</c>), not <c>[]</c>.
+ The notation <c>[]</c> specifies the singleton type for the empty list.
+ </p>
+ <p>
+ For convenience, the following types are also built-in.
+ They can be thought as predefined aliases for the type unions also shown in
+ the table. (Some type unions below slightly abuse the syntax of types.)
+ </p>
+ <table>
+ <row>
+ <cell><b>Built-in type</b></cell><cell><b>Stands for</b></cell>
+ </row>
+ <row>
+ <cell><c>term()</c></cell><cell><c>any()</c></cell>
+ </row>
+ <row>
+ <cell><c>boolean()</c></cell><cell><c>'false' | 'true'</c></cell>
+ </row>
+ <row>
+ <cell><c>byte()</c></cell><cell><c>0..255</c></cell>
+ </row>
+ <row>
+ <cell><c>char()</c></cell><cell><c>0..16#10ffff</c></cell>
+ </row>
+ <row>
+ <cell><c>non_neg_integer()</c></cell><cell><c>0..</c></cell>
+ </row>
+ <row>
+ <cell><c>pos_integer()</c></cell><cell><c>1..</c></cell>
+ </row>
+ <row>
+ <cell><c>neg_integer()</c></cell><cell><c>..-1</c></cell>
+ </row>
+ <row>
+ <cell><c>number()</c></cell><cell><c>integer() | float()</c></cell>
+ </row>
+ <row>
+ <cell><c>list()</c></cell><cell><c>[any()]</c></cell>
+ </row>
+ <row>
+ <cell><c>maybe_improper_list()</c></cell><cell><c>maybe_improper_list(any(), any())</c></cell>
+ </row>
+ <row>
+ <cell><c>maybe_improper_list(T)</c></cell><cell><c>maybe_improper_list(T, any())</c></cell>
+ </row>
+ <row>
+ <cell><c>string()</c></cell><cell><c>[char()]</c></cell>
+ </row>
+ <row>
+ <cell><c>nonempty_string()</c></cell><cell><c>[char(),...]</c></cell>
+ </row>
+ <row>
+ <cell><c>iolist()</c></cell><cell><c>maybe_improper_list(char() | binary() | iolist(), binary() | [])</c></cell>
+ </row>
+ <row>
+ <cell><c>module()</c></cell><cell><c>atom()</c></cell>
+ </row>
+ <row>
+ <cell><c>mfa()</c></cell><cell><c>{atom(),atom(),byte()}</c></cell>
+ </row>
+ <row>
+ <cell><c>node()</c></cell><cell><c>atom()</c></cell>
+ </row>
+ <row>
+ <cell><c>timeout()</c></cell><cell><c>'infinity' | non_neg_integer()</c></cell>
+ </row>
+ <row>
+ <cell><c>no_return()</c></cell><cell><c>none()</c></cell>
+ </row>
+ </table>
+
+ <p>
+ Users are not allowed to define types with the same names as the
+ predefined or built-in ones. This is checked by the compiler and
+ its violation results in a compilation error.
+ (For bootstrapping purposes, it can also result to just a warning if this
+ involves a built-in type which has just been introduced.)
+ </p>
+ <note>
+ The following built-in list types also exist,
+ but they are expected to be rarely used. Hence, they have long names:
+ </note>
+ <pre>
nonempty_maybe_improper_list(Type) :: nonempty_maybe_improper_list(Type, any())
-nonempty_maybe_improper_list() :: nonempty_maybe_improper_list(any())
- </pre>
- <p>
- where the following two types
- define the set of Erlang terms one would expect:
- </p>
- <pre>
+nonempty_maybe_improper_list() :: nonempty_maybe_improper_list(any())</pre>
+ <p>
+ where the following two types
+ define the set of Erlang terms one would expect:
+ </p>
+ <pre>
nonempty_improper_list(Type1, Type2)
-nonempty_maybe_improper_list(Type1, Type2)
- </pre>
- <p>
- Also for convenience, we allow for record notation to be used.
- Records are just shorthands for the corresponding tuples.
- </p>
- <pre>
+nonempty_maybe_improper_list(Type1, Type2)</pre>
+ <p>
+ Also for convenience, we allow for record notation to be used.
+ Records are just shorthands for the corresponding tuples.
+ </p>
+ <pre>
Record :: #Erlang_Atom{}
- | #Erlang_Atom{Fields}
- </pre>
+ | #Erlang_Atom{Fields}</pre>
+ <p>
+ Records have been extended to possibly contain type information.
+ This is described in the sub-section <seealso marker="#typeinrecords">"Type information in record declarations"</seealso> below.
+ </p>
+ </section>
+
+ <section>
+ <title>Type declarations of user-defined types</title>
<p>
- Records have been extended to possibly contain type information.
- This is described in the sub-section <seealso marker="#typeinrecords">"Type information in record declarations"</seealso> below.
- </p>
- </section>
-
- <section>
- <title>Type declarations of user-defined types</title>
- <p>
- As seen, the basic syntax of a type is an atom followed by closed
- parentheses. New types are declared using '-type' compiler attributes
- as in the following:
- </p>
- <pre>
--type my_type() :: Type.
- </pre>
- <p>
- where the type name is an atom (<c>'my_type'</c> in the above) followed by
- parenthesis. Type is a type as defined in the previous section.
- A current restriction is that Type can contain only predefined types
- or user-defined types which have been previously defined.
- This restriction is enforced by the compiler and results in a
- compilation error. (A similar restriction currently exists for records).
- </p>
- <p>
- This means that currently general recursive types cannot be defined.
- Lifting this restriction is future work.
- </p>
- <p>
- Type declarations can also be parameterized by including type variables
- between the parentheses. The syntax of type variables is the same as
- Erlang variables (starts with an upper case letter).
- Naturally, these variables can - and should - appear on the RHS of the
- definition. A concrete example appears below:
- </p>
- <pre>
--type orddict(Key, Val) :: [{Key, Val}].
- </pre>
-
- </section>
-
- <marker id="typeinrecords"/>
- <section>
- <title>
- Type information in record declarations
- </title>
- <p>
- The types of record fields can be specified in the declaration of the
- record. The syntax for this is:
- </p>
- <pre>
--record(rec, {field1 :: Type1, field2, field3 :: Type3}).
- </pre>
- <p>
- For fields without type annotations, their type defaults to any().
- I.e., the above is a shorthand for:
- </p>
- <pre>
--record(rec, {field1 :: Type1, field2 :: any(), field3 :: Type3}).
- </pre>
- <p>
- In the presence of initial values for fields,
- the type must be declared after the initialization as in the following:
- </p>
- <pre>
--record(rec, {field1 = [] :: Type1, field2, field3 = 42 :: Type3}).
- </pre>
- <p>
- Naturally, the initial values for fields should be compatible
- with (i.e. a member of) the corresponding types.
- This is checked by the compiler and results in a compilation error
- if a violation is detected. For fields without initial values,
- the singleton type <c>'undefined'</c> is added to all declared types.
- In other words, the following two record declarations have identical
- effects:
- </p>
- <pre>
+ As seen, the basic syntax of a type is an atom followed by closed
+ parentheses. New types are declared using '-type' and '-opaque'
+ compiler attributes as in the following:
+ </p>
+ <pre>
+-type my_struct_type() :: Type.
+-opaque my_opaq_type() :: Type.</pre>
+ <p>
+ where the type name is an atom (<c>'my_struct_type'</c> in the above)
+ followed by parentheses. Type is a type as defined in the
+ previous section.
+ A current restriction is that Type can contain only predefined types,
+ or user-defined types which are either module-local (i.e., with a
+ definition that is present in the code of the module) or are remote
+ types (i.e., types defined in and exported by other modules; see below).
+ For module-local types, the restriction that their definition
+ exists in the module is enforced by the compiler and results in a
+ compilation error. (A similar restriction currently exists for records.)
+ </p>
+ <p>
+ Type declarations can also be parameterized by including type variables
+ between the parentheses. The syntax of type variables is the same as
+ Erlang variables (starts with an upper case letter).
+ Naturally, these variables can - and should - appear on the RHS of the
+ definition. A concrete example appears below:
+ </p>
+ <pre>
+-type orddict(Key, Val) :: [{Key, Val}].</pre>
+ <p>
+ A module can export some types in order to declare that other modules
+ are allowed to refer to them as <em>remote types</em>.
+ This declaration has the following form:
+ <pre>
+-export_type([T1/A1, ..., Tk/Ak]).</pre>
+ where the Ti's are atoms (the name of the type) and the Ai's are their
+ arguments. An example is given below:
+ <pre>
+-export_type([my_struct_type/0, orddict/2]).</pre>
+ Assuming that these types are exported from module <c>'mod'</c> then
+ one can refer to them from other modules using remote type expressions
+ like those below:
+ <pre>
+mod:my_struct_type()
+mod:orddict(atom(), term())</pre>
+ One is not allowed to refer to types which are not declared as exported.
+ </p>
+ <p>
+ Types declared as <c>opaque</c> represent sets of terms whose
+ structure is not supposed to be visible in any way outside of
+ their defining module (i.e., only the module defining them is
+ allowed to depend on their term structure). Consequently, such
+ types do not make much sense as module local - module local
+ types are not accessible by other modules anyway - and should
+ always be exported.
+ </p>
+ </section>
+
+ <marker id="typeinrecords"/>
+ <section>
+ <title>Type information in record declarations</title>
+ <p>
+ The types of record fields can be specified in the declaration of the
+ record. The syntax for this is:
+ </p>
+ <pre>
+-record(rec, {field1 :: Type1, field2, field3 :: Type3}).</pre>
+ <p>
+ For fields without type annotations, their type defaults to any().
+ I.e., the above is a shorthand for:
+ </p>
+ <pre>
+-record(rec, {field1 :: Type1, field2 :: any(), field3 :: Type3}).</pre>
+ <p>
+ In the presence of initial values for fields,
+ the type must be declared after the initialization as in the following:
+ </p>
+ <pre>
+-record(rec, {field1 = [] :: Type1, field2, field3 = 42 :: Type3}).</pre>
+ <p>
+ Naturally, the initial values for fields should be compatible
+ with (i.e. a member of) the corresponding types.
+ This is checked by the compiler and results in a compilation error
+ if a violation is detected. For fields without initial values,
+ the singleton type <c>'undefined'</c> is added to all declared types.
+ In other words, the following two record declarations have identical
+ effects:
+ </p>
+ <pre>
-record(rec, {f1 = 42 :: integer(),
f2 :: float(),
- f3 :: 'a' | 'b').
+ f3 :: 'a' | 'b'}).
-record(rec, {f1 = 42 :: integer(),
f2 :: 'undefined' | float(),
- f3 :: 'undefined' | 'a' | 'b').
- </pre>
- <p>
- For this reason, it is recommended that records contain initializers,
- whenever possible.
- </p>
- <p>
- Any record, containing type information or not, once defined,
- can be used as a type using the syntax:
- </p>
- <pre>
-#rec{}
- </pre>
- <p>
- In addition, the record fields can be further specified when using
- a record type by adding type information about the field in the following
- manner:
- </p>
- <pre>
-#rec{some_field :: Type}
- </pre>
- <p>
- Any unspecified fields are assumed to have the type in the original
- record declaration.
- </p>
- </section>
+ f3 :: 'undefined' | 'a' | 'b'}).</pre>
+ <p>
+ For this reason, it is recommended that records contain initializers,
+ whenever possible.
+ </p>
+ <p>
+ Any record, containing type information or not, once defined,
+ can be used as a type using the syntax:
+ </p>
+ <pre>
+#rec{}</pre>
+ <p>
+ In addition, the record fields can be further specified when using
+ a record type by adding type information about the field in
+ the following manner:
+ </p>
+ <pre>
+#rec{some_field :: Type}</pre>
+ <p>
+ Any unspecified fields are assumed to have the type in the original
+ record declaration.
+ </p>
+ </section>
- <section>
- <title>Specifications (contracts) for functions</title>
- <p>
- A contract (or specification) for a function is given using the new
- compiler attribute <c>'-spec'</c>. The basic format is as follows:
- </p>
- <pre>
--spec Module:Function(ArgType1, ..., ArgTypeN) -> ReturnType.
- </pre>
- <p>
- The arity of the function has to match the number of arguments,
- or else a compilation error occurs.
- </p>
- <p>
- This form can also be used in header files (.hrl) to declare type
- information for exported functions.
- Then these header files can be included in files that (implicitly or
- explicitly) import these functions.
- </p>
- <p>
- For most uses within a given module, the following shorthand is allowed:
- </p>
- <pre>
--spec Function(ArgType1, ..., ArgTypeN) -> ReturnType.
- </pre>
- <p>
- Also, for documentation purposes, argument names can be given:
- </p>
- <pre>
--spec Function(ArgName1 :: Type1, ..., ArgNameN :: TypeN) -> RT.
- </pre>
- <p>
- A function specification can be overloaded.
- That is, it can have several types, separated by a semicolon (<c>;</c>):
- </p>
- <pre>
+ <section>
+ <title>Specifications for functions</title>
+ <p>
+ A specification (or contract) for a function is given using the new
+ compiler attribute <c>'-spec'</c>. The general format is as follows:
+ </p>
+ <pre>
+-spec Module:Function(ArgType1, ..., ArgTypeN) -> ReturnType.</pre>
+ <p>
+ The arity of the function has to match the number of arguments,
+ or else a compilation error occurs.
+ </p>
+ <p>
+ This form can also be used in header files (.hrl) to declare type
+ information for exported functions.
+ Then these header files can be included in files that (implicitly or
+ explicitly) import these functions.
+ </p>
+ <p>
+ For most uses within a given module, the following shorthand suffices:
+ </p>
+ <pre>
+-spec Function(ArgType1, ..., ArgTypeN) -> ReturnType.</pre>
+ <p>
+ Also, for documentation purposes, argument names can be given:
+ </p>
+ <pre>
+-spec Function(ArgName1 :: Type1, ..., ArgNameN :: TypeN) -> RT.</pre>
+ <p>
+ A function specification can be overloaded.
+ That is, it can have several types, separated by a semicolon (<c>;</c>):
+ </p>
+ <pre>
-spec foo(T1, T2) -> T3
- ; (T4, T5) -> T6.
- </pre>
- <p>
- A current restriction, which currently results in a warning
- (OBS: not an error) by the compiler, is that the domains of the argument
- types cannot be overlapping.
- For example, the following specification results in a warning:
- </p>
- <pre>
+ ; (T4, T5) -> T6.</pre>
+ <p>
+ A current restriction, which currently results in a warning
+ (OBS: not an error) by the compiler, is that the domains of
+ the argument types cannot be overlapping.
+ For example, the following specification results in a warning:
+ </p>
+ <pre>
-spec foo(pos_integer()) -> pos_integer()
- ; (integer()) -> integer().
- </pre>
- <p>
- Type variables can be used in specifications to specify relations for
- the input and output arguments of a function.
- For example, the following specification defines the type of a
- polymorphic identity function:
- </p>
- <pre>
--spec id(X) -> X.
- </pre>
- <p>
- However, note that the above specification does not restrict the input
- and output type in any way.
- We can constrain these types by guard-like subtype constraints:
- </p>
- <pre>
--spec id(X) -> X when is_subtype(X, tuple()).
- </pre>
- <p>
- and provide bounded quantification. Currently,
- the <c>is_subtype/2</c> guard is the only guard which can
- be used in a <c>'-spec'</c> attribute.
- </p>
- <p>
- The scope of an <c>is_subtype/2</c> constraint is the
- <c>(...) -> RetType</c>
- specification after which it appears. To avoid confusion,
- we suggest that different variables are used in different constituents of
- an overloaded contract as in the example below:
- </p>
- <pre>
--spec foo({X, integer()}) -> X when is_subtype(X, atom())
- ; ([Y]) -> Y when is_subtype(Y, number()).
- </pre>
- <p>
- Some functions in Erlang are not meant to return;
- either because they define servers or because they are used to
- throw exceptions as the function below:
- </p>
- <pre>
-my_error(Err) -> erlang:throw({error, Err}).
- </pre>
- <p>
- For such functions we recommend the use of the special no_return()
- type for their "return", via a contract of the form:
- </p>
- <pre>
--spec my_error(term()) -> no_return().
- </pre>
- </section>
+ ; (integer()) -> integer().</pre>
+ <p>
+ Type variables can be used in specifications to specify relations for
+ the input and output arguments of a function.
+ For example, the following specification defines the type of a
+ polymorphic identity function:
+ </p>
+ <pre>
+-spec id(X) -> X.</pre>
+ <p>
+ However, note that the above specification does not restrict the input
+ and output type in any way.
+ We can constrain these types by guard-like subtype constraints:
+ </p>
+ <pre>
+-spec id(X) -> X when is_subtype(X, tuple()).</pre>
+ <p>
+ or equivalently by the more succinct and more modern form of the above:
+ </p>
+ <pre>
+-spec id(X) -> X when X :: tuple().</pre>
+ <p>
+ and provide bounded quantification. Currently, the <c>::</c> constraint
+ (the <c>is_subtype/2</c> guard) is the only guard constraint which can
+ be used in the <c>'when'</c> part of a <c>'-spec'</c> attribute.
+ </p>
+ <p>
+ The scope of an <c>::</c> constraint is the
+ <c>(...) -> RetType</c>
+ specification after which it appears. To avoid confusion,
+ we suggest that different variables are used in different
+ constituents of an overloaded contract as in the example below:
+ </p>
+ <pre>
+-spec foo({X, integer()}) -> X when X :: atom()
+ ; ([Y]) -> Y when Y :: number().</pre>
+ <p>
+ Some functions in Erlang are not meant to return;
+ either because they define servers or because they are used to
+ throw exceptions as the function below:
+ </p>
+ <pre>
+my_error(Err) -> erlang:throw({error, Err}).</pre>
+ <p>
+ For such functions we recommend the use of the special no_return()
+ type for their "return", via a contract of the form:
+ </p>
+ <pre>
+-spec my_error(term()) -> no_return().</pre>
+ </section>
</chapter>
diff --git a/system/doc/top/Makefile b/system/doc/top/Makefile
index 154deb006b..aac90fcaa4 100644
--- a/system/doc/top/Makefile
+++ b/system/doc/top/Makefile
@@ -111,6 +111,10 @@ GLOSSARY = $(HTMLDIR)/glossary.html
GLOSSARY_SRC = $(ERL_TOP)/system/internal_tools/doctools/src/glossary.erl
GLOSSARY_SCRIPT = $(EBIN)/glossary.$(EMULATOR)
+TEMPLATES = \
+ templates/index.html.src \
+ templates/applications.html.src
+
#--------------------------------------------------------------------------
$(INDEX_SCRIPT): $(INDEX_SRC)
@@ -119,8 +123,14 @@ $(INDEX_SCRIPT): $(INDEX_SRC)
# We don't list toc_*.html as targets because we don't know
$(HTMLDIR)/index.html + $(HTMLDIR)/applications.html: $(INDEX_SCRIPT)
echo "Generating index $@"
- $(ERL) -noshell -pa $(EBIN) -s erl_html_tools top_index $(ERL_TOP) \
- $(HTMLDIR) $(SYSTEM_VSN) -s erlang halt
+# Check if we are building the index from source or an installed release
+ if test "$$RELEASE_ROOT" = "" ; then \
+ $(ERL) -noshell -pa $(EBIN) -s erl_html_tools top_index src $(ERL_TOP) \
+ $(HTMLDIR) $(SYSTEM_VSN) -s erlang halt ;\
+ else \
+ $(ERL) -noshell -pa $(EBIN) -s erl_html_tools top_index rel $(RELEASE_ROOT) \
+ $(HTMLDIR) $(SYSTEM_VSN) -s erlang halt ;\
+ fi
#--------------------------------------------------------------------------
@@ -139,8 +149,15 @@ $(MAN_INDEX_SCRIPT): $(MAN_INDEX_SRC)
$(ERLC) -o$(EBIN) +warn_unused_vars $<
$(MAN_INDEX): $(MAN_INDEX_SCRIPT)
- $(ERL) -noshell -pa $(EBIN) -s otp_man_index gen $(ERL_TOP) $@ \
- -s erlang halt
+# Check if we are building the index from source or an installed release
+ if test "$$RELEASE_ROOT" = "" ; then \
+ $(ERL) -noshell -pa $(EBIN) -s otp_man_index gen src $(ERL_TOP) $@ \
+ -s erlang halt ;\
+ else \
+ $(ERL) -noshell -pa $(EBIN) -s otp_man_index gen rel $(RELEASE_ROOT) $@ \
+ -s erlang halt ;\
+ fi
+
#--------------------------------------------------------------------------
@@ -226,7 +243,11 @@ release_docs_spec: docs
$(INSTALL_DIR) $(RELSYSDIR)/js
$(INSTALL_DATA) \
$(JAVASCRIPT) $(RELSYSDIR)/js
- $(INSTALL_DATA) $(INDEX_FILES) $(MAN_INDEX) $(TOP_HTML_FILES) $(RELSYSDIR)
+ $(INSTALL_DATA) $(INDEX_FILES) $(MAN_INDEX) $(TOP_HTML_FILES) $(RELSYSDIR)
+ $(INSTALL_DIR) $(RELSYSDIR)/docbuild
+ $(INSTALL_DATA) $(INDEX_SCRIPT) $(MAN_INDEX_SCRIPT) $(JAVASCRIPT_BUILD_SCRIPT) \
+ $(INDEX_SRC) $(MAN_INDEX_SRC) $(JAVASCRIPT_BUILD_SCRIPT_SRC) \
+ $(TEMPLATES) $(RELSYSDIR)/docbuild
release_spec:
diff --git a/system/doc/top/src/erl_html_tools.erl b/system/doc/top/src/erl_html_tools.erl
index c920245f94..599268804e 100644
--- a/system/doc/top/src/erl_html_tools.erl
+++ b/system/doc/top/src/erl_html_tools.erl
@@ -26,7 +26,7 @@
%%-----------------------------------------------------------------
-module(erl_html_tools).
--export([top_index/0,top_index/1,top_index/3,top_index_silent/3]).
+-export([top_index/0,top_index/1,top_index/4,top_index_silent/3]).
-include_lib("kernel/include/file.hrl").
@@ -40,7 +40,8 @@ group_order() ->
{test, "Test"},
{doc, "Documentation"},
{orb, "Object Request Broker & IDL"},
- {misc, "Miscellaneous"}
+ {misc, "Miscellaneous"},
+ {eric, "Ericsson Internal"}
].
top_index() ->
@@ -49,19 +50,22 @@ top_index() ->
io:format("Variable ERL_TOP is required\n",[]);
Value ->
{_,RelName} = init:script_id(),
- top_index(Value, filename:join(Value, "doc"), RelName)
+ top_index(src, Value, filename:join(Value, "doc"), RelName)
end.
-top_index([RootDir, DestDir, OtpRel])
+top_index([src, RootDir, DestDir, OtpRel])
when is_atom(RootDir), is_atom(DestDir), is_atom(OtpRel) ->
- top_index(atom_to_list(RootDir), atom_to_list(DestDir), atom_to_list(OtpRel));
-top_index(RootDir) when is_atom(RootDir) ->
+ top_index(src, atom_to_list(RootDir), atom_to_list(DestDir), atom_to_list(OtpRel));
+top_index([rel, RootDir, DestDir, OtpRel])
+ when is_atom(RootDir), is_atom(DestDir), is_atom(OtpRel) ->
+ top_index(rel, atom_to_list(RootDir), atom_to_list(DestDir), atom_to_list(OtpRel));
+top_index(RootDir) when is_atom(RootDir) ->
{_,RelName} = init:script_id(),
- top_index(RootDir, filename:join(RootDir, "doc"), RelName).
+ top_index(rel, RootDir, filename:join(RootDir, "doc"), RelName).
-top_index(RootDir, DestDir, OtpRel) ->
+top_index(Source, RootDir, DestDir, OtpRel) ->
report("****\nRootDir: ~p", [RootDir]),
report("****\nDestDir: ~p", [DestDir]),
report("****\nOtpRel: ~p", [OtpRel]),
@@ -72,13 +76,13 @@ top_index(RootDir, DestDir, OtpRel) ->
report("****\nTemplates: ~p", [Templates]),
Bases = [{"../lib/", filename:join(RootDir,"lib")},
{"../", RootDir}],
- Groups = find_information(Bases),
+ Groups = find_information(Source, Bases),
report("****\nGroups: ~p", [Groups]),
process_templates(Templates, DestDir, Groups).
top_index_silent(RootDir, DestDir, OtpRel) ->
put(silent,true),
- Result = top_index(RootDir, DestDir, OtpRel),
+ Result = top_index(rel, RootDir, DestDir, OtpRel),
erase(silent),
Result.
@@ -159,8 +163,8 @@ find_templates([], AllSearchPaths) ->
% This function read all application names and if present all "info" files.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-find_information(Bases) ->
- Paths = find_application_paths(Bases),
+find_information(Source, Bases) ->
+ Paths = find_application_paths(Source, Bases),
% report("****\nPaths: ~p", [Paths]),
Apps = find_application_infos(Paths),
% report("****\nApps: ~p", [Apps]),
@@ -176,35 +180,47 @@ find_information(Bases) ->
%
% We know URL ends in a slash.
-find_application_paths([]) ->
+find_application_paths(_, []) ->
[];
-find_application_paths([{URL, Dir} | Paths]) ->
+find_application_paths(Source, [{URL, Dir} | Paths]) ->
+
+ AppDirs = get_app_dirs(Dir),
+ AppPaths = get_app_paths(Source, AppDirs, URL),
+ AppPaths ++ find_application_paths(Source, Paths).
+
+
+get_app_paths(src, AppDirs, URL) ->
Sub1 = "doc/html/index.html",
%% Sub2 = "doc/index.html",
+ lists:map(
+ fun({App, AppPath}) ->
+ VsnFile = filename:join(AppPath, "vsn.mk"),
+ VsnStr =
+ case file:read_file(VsnFile) of
+ {ok, Bin} ->
+ case re:run(Bin, ".*VSN\s*=\s*([0-9\.]+).*",[{capture,[1],list}]) of
+ {match, [V]} ->
+ V;
+ nomatch ->
+ exit(io_lib:format("No VSN variable found in ~s\n",
+ [VsnFile]))
+ end;
+ {error, Reason} ->
+ exit(io_lib:format("~p : ~s\n", [Reason, VsnFile]))
+ end,
+ AppURL = URL ++ App ++ "-" ++ VsnStr,
+ {App, VsnStr, AppPath, AppURL ++ "/" ++ Sub1}
+ end, AppDirs);
+get_app_paths(rel, AppDirs, URL) ->
+ Sub1 = "doc/html/index.html",
+%% Sub2 = "doc/index.html",
+ lists:map(
+ fun({App, AppPath}) ->
+ [AppName, VsnStr] = string:tokens(App, "-"),
+ AppURL = URL ++ App,
+ {AppName, VsnStr, AppPath, AppURL ++ "/" ++ Sub1}
+ end, AppDirs).
- AppDirs = get_app_dirs(Dir),
-
- AppPaths =
- lists:map(
- fun({App, AppPath}) ->
- VsnFile = filename:join(AppPath, "vsn.mk"),
- VsnStr =
- case file:read_file(VsnFile) of
- {ok, Bin} ->
- case re:run(Bin, ".*VSN\s*=\s*([0-9\.]+).*",[{capture,[1],list}]) of
- {match, [V]} ->
- V;
- nomatch ->
- exit(io_lib:format("No VSN variable found in ~s\n",
- [VsnFile]))
- end;
- {error, Reason} ->
- exit(io_lib:format("~p : ~s\n", [Reason, VsnFile]))
- end,
- AppURL = URL ++ App ++ "-" ++ VsnStr,
- {App, VsnStr, AppPath, AppURL ++ "/" ++ Sub1}
- end, AppDirs),
- AppPaths ++ find_application_paths(Paths).
get_app_dirs(Dir) ->
{ok, Files} = file:list_dir(Dir),
@@ -212,7 +228,7 @@ get_app_dirs(Dir) ->
lists:map(fun(File) -> {File, filename:join([Dir, File])} end, Files),
lists:zf(fun is_app_with_doc/1, AFiles).
-is_app_with_doc({"." ++ ADir, _APath}) ->
+is_app_with_doc({"." ++ _ADir, _APath}) ->
false;
is_app_with_doc({ADir, APath}) ->
case file:read_file_info(filename:join([APath, "info"])) of
diff --git a/system/doc/top/src/otp_man_index.erl b/system/doc/top/src/otp_man_index.erl
index 0fdc531b37..4ad975c53d 100644
--- a/system/doc/top/src/otp_man_index.erl
+++ b/system/doc/top/src/otp_man_index.erl
@@ -27,14 +27,20 @@
-module(otp_man_index).
--export([gen/1]).
+-export([gen/1, gen/2]).
-include_lib("kernel/include/file.hrl").
-gen([RootDir, OutFile]) when is_atom(RootDir), is_atom(OutFile)->
+gen([Source, RootDir, OutFile]) when is_atom(RootDir), is_atom(OutFile)->
+ gen(Source, RootDir, OutFile).
+
+gen(RootDir, OutFile) ->
+ gen(rel, RootDir, OutFile).
+
+gen(Source, RootDir, OutFile) ->
Bases = [{"../lib/", filename:join(RootDir, "lib")},
{"../", RootDir}],
- Apps = find_application_paths(Bases),
+ Apps = find_application_paths(Source, Bases),
RefPages = find_ref_files(Apps),
gen_html(RefPages, atom_to_list(OutFile)).
@@ -81,43 +87,52 @@ find_ref_files([{App, Vsn, AppPath, RelPath} |Apps], Acc) ->
find_ref_files(Apps, Refs2 ++ Acc)
end.
-find_application_paths([]) ->
+find_application_paths(_, []) ->
[];
-find_application_paths([{URL, Dir} | Paths]) ->
- Sub1 = "doc/html",
+find_application_paths(Source, [{URL, Dir} | Paths]) ->
AppDirs = get_app_dirs(Dir),
-
- AppPaths =
- lists:map(
- fun({App, AppPath}) ->
- VsnFile = filename:join(AppPath, "vsn.mk"),
- VsnStr =
- case file:read_file(VsnFile) of
- {ok, Bin} ->
- case re:run(Bin, ".*VSN\s*=\s*([0-9\.]+).*",[{capture,[1],list}]) of
- {match, [V]} ->
- V;
- nomatch ->
- exit(io_lib:format("No VSN variable found in ~s\n",
- [VsnFile]))
- end;
- {error, Reason} ->
- exit(io_lib:format("~p : ~s\n", [Reason, VsnFile]))
- end,
- AppURL = URL ++ App ++ "-" ++ VsnStr,
- {App, VsnStr, AppPath ++ "/" ++ Sub1, AppURL ++ "/" ++ Sub1}
- end, AppDirs),
- AppPaths ++ find_application_paths(Paths).
-
+ AppPaths = get_app_paths(Source, AppDirs, URL),
+ AppPaths ++ find_application_paths(Source, Paths).
+get_app_paths(src, AppDirs, URL) ->
+ Sub1 = "doc/html",
+ lists:map(
+ fun({App, AppPath}) ->
+ VsnFile = filename:join(AppPath, "vsn.mk"),
+ VsnStr =
+ case file:read_file(VsnFile) of
+ {ok, Bin} ->
+ case re:run(Bin, ".*VSN\s*=\s*([0-9\.]+).*",[{capture,[1],list}]) of
+ {match, [V]} ->
+ V;
+ nomatch ->
+ exit(io_lib:format("No VSN variable found in ~s\n",
+ [VsnFile]))
+ end;
+ {error, Reason} ->
+ exit(io_lib:format("~p : ~s\n", [Reason, VsnFile]))
+ end,
+ AppURL = URL ++ App ++ "-" ++ VsnStr,
+ {App, VsnStr, AppPath ++ "/" ++ Sub1, AppURL ++ "/" ++ Sub1}
+ end, AppDirs);
+get_app_paths(rel, AppDirs, URL) ->
+ Sub1 = "doc/html",
+ lists:map(
+ fun({App, AppPath}) ->
+ [AppName, VsnStr] = string:tokens(App, "-"),
+ AppURL = URL ++ App,
+ {AppName, VsnStr, AppPath ++ "/" ++ Sub1, AppURL ++ "/" ++ Sub1}
+ end, AppDirs).
+
+
get_app_dirs(Dir) ->
{ok, Files} = file:list_dir(Dir),
AFiles =
lists:map(fun(File) -> {File, filename:join([Dir, File])} end, Files),
lists:zf(fun is_app_with_doc/1, AFiles).
-is_app_with_doc({"." ++ ADir, _APath}) ->
+is_app_with_doc({"." ++ _ADir, _APath}) ->
false;
is_app_with_doc({ADir, APath}) ->
case file:read_file_info(filename:join([APath, "info"])) of
diff --git a/system/doc/top/templates/index.html.src b/system/doc/top/templates/index.html.src
index 88d425ac1d..655f532a5d 100644
--- a/system/doc/top/templates/index.html.src
+++ b/system/doc/top/templates/index.html.src
@@ -39,10 +39,6 @@ under the License.
<small><a href="applications.html">Applications</a><br>
<a href="man_index.html">Modules</a></small>
<p/>
-<small><a href="highlights.html">Release highlights</a><br/>
-<a href="incompatible.html">Potential incompatibilities</a><br/>
-</small>
-<br>
<a href="javascript:openAllFlips()">Expand All</a><br>
<a href="javascript:closeAllFlips()">Contract All</a>
<p/>
diff --git a/system/doc/tutorial/c_port.xmlsrc b/system/doc/tutorial/c_port.xmlsrc
index 7e6034807b..b4caa07578 100644
--- a/system/doc/tutorial/c_port.xmlsrc
+++ b/system/doc/tutorial/c_port.xmlsrc
@@ -70,7 +70,7 @@ loop(Port) ->
{call, Caller, Msg} ->
Port ! {self(), {command, encode(Msg)}},
receive
-\011{Port, {data, Data}} ->
+ {Port, {data, Data}} ->
Caller ! {complex, decode(Data)}
end,
loop(Port)